com.samsung.spen.SPenPopupSurface.java Source code

Java tutorial

Introduction

Here is the source code for com.samsung.spen.SPenPopupSurface.java

Source

/*
 * Copyright (c) 2015 Samsung Electronics, Co. Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.samsung.spen;

import java.io.IOException;

import org.apache.cordova.PluginResult;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.samsung.android.sdk.SsdkUnsupportedException;
import com.samsung.android.sdk.pen.Spen;
import com.samsung.android.sdk.pen.SpenSettingPenInfo;
import com.samsung.android.sdk.pen.document.SpenNoteDoc;
import com.samsung.android.sdk.pen.engine.SpenSurfaceView;
import com.samsung.android.sdk.pen.settingui.SpenSettingPenLayout;
import com.samsung.android.sdk.pen.settingui.SpenSettingSelectionLayout;
import com.samsung.spen.SpenException.SpenExceptionType;

/**
 * Class used for creating and handling popup surfaces.
 *
 */
public class SPenPopupSurface extends SpenSurface {

    private int mCurrentPageindex;
    private Dialog mDialog;
    private OrientationEventListener mOrientationListener;
    private RelativeLayout spenSurfaceViewContainer;
    private SpenSettingPenLayout mSpenSettingPenLayout;
    private SpenSettingSelectionLayout mSelectionSettingView;
    private AlertDialog mADiscardDialog;
    private Point mPageDocSizes = new Point();

    private static final String TAG = "SPenPopupSurface";

    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            int orientation = msg.getData().getInt("orientation");
            //            handleOrientationChange(orientation);
        }
    };

    /**
     * Constructor for SPenPopupSurface
     * 
     * @param contextParams
     * @param option
     * 
     */
    public SPenPopupSurface(SpenContextParams contextParams, SpenTrayBarOptions option) {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside SPenPopupSurface");
        }
        mContextParams = contextParams;
        mOptions = option;
        createRelativeLayout(mContextParams.getSpenCustomDrawPlugin().cordova.getActivity());
    }

    /**
     * create RelativeLayout
     * 
     * @param context
     * 
     */

    private void createRelativeLayout(Context context) {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside initContextDetails");
        }
        if (mRelativeLayout == null) {
            mRelativeLayout = new RelativeLayout(context);
        }
        if (mRelativeLayout.getParent() != null) {
            ((ViewGroup) mRelativeLayout.getParent()).removeView(mRelativeLayout);
        }
        mRelativeLayout.removeAllViews();
    }

    /**
     * create SPen surface
     * 
     * @return true if surface created otherwise false
     */
    boolean createSPenSurface() {
        Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
        boolean isSurface = true;
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside createSPenSurface");
        }
        if (mDialog == null) {
            mDialog = new Dialog(activity);
            mDialog.setCanceledOnTouchOutside(false);
            mDialog.setOnDismissListener(new OnDismissListener() {

                @Override
                public void onDismiss(DialogInterface dialog) {
                }
            });
            mDialog.setOnCancelListener(new OnCancelListener() {

                @Override
                public void onCancel(DialogInterface dialog) {
                    if (mSpenSettingPenLayout != null) {
                        mSpenSettingPenLayout.setVisibility(View.GONE);
                    }
                    if (mSelectionSettingView != null) {
                        mSelectionSettingView.setVisibility(View.GONE);
                    }
                    mSpenSurfaceView.closeControl();
                }
            });
            mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "Dialog was null, creating new dialog. Dialog:" + mDialog.toString());
            }
        }

        mRelativeLayout.setBackgroundColor(mOptions.getColor());
        // Adding top traybar buttons
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);

        int resId = activity.getResources().getIdentifier("spentraybar_top", "layout", activity.getPackageName());
        RelativeLayout traybar_top = (RelativeLayout) View.inflate(activity, resId, null);
        lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        mRelativeLayout.addView(traybar_top, lp);

        // Adding bottom traybar
        RelativeLayout traybar_bottom = null;
        if ((mOptions.getsPenFlags() & Utils.FLAG_ADD_PAGE) == Utils.FLAG_ADD_PAGE) {
            resId = activity.getResources().getIdentifier("spentraybar_bottom", "layout",
                    activity.getPackageName());
            traybar_bottom = (RelativeLayout) View.inflate(activity, resId, null);
            lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            mRelativeLayout.addView(traybar_bottom, lp);
        }

        final Point point = getWidthAndHeightForPageDoc();
        mPageDocSizes = point;

        try {
            Spen spenPackage = new Spen();
            boolean isStatic = false;
            resId = activity.getResources().getIdentifier("spen_static", "bool", activity.getPackageName());
            try {
                if (resId != 0) {
                    isStatic = activity.getResources().getBoolean(resId);
                }
            } catch (Resources.NotFoundException re) {
                isStatic = false;
            }

            if (isStatic) {
                spenPackage.initialize(activity.getApplicationContext(), 5, Spen.SPEN_STATIC_LIB_MODE);
            } else {
                spenPackage.initialize(activity.getApplicationContext());
            }

            mSpenSurfaceView = new SpenSurfaceView(activity.getApplicationContext());
            lp = new RelativeLayout.LayoutParams(point.x, point.y);
            lp.addRule(RelativeLayout.BELOW, traybar_top.getId());

            if (traybar_bottom != null) {
                lp.addRule(RelativeLayout.ABOVE, traybar_bottom.getId());
            }

            spenSurfaceViewContainer = new RelativeLayout(activity);
            spenSurfaceViewContainer.addView(mSpenSurfaceView);
            mRelativeLayout.addView(spenSurfaceViewContainer, lp);
            int xValue = point.x;
            int yValue = point.y - (int) (((float) 24) * activity.getResources().getDisplayMetrics().density);
            mSpenNoteDoc = new SpenNoteDoc(activity.getApplicationContext(), xValue, yValue);
            mSpenPageDoc = mSpenNoteDoc.appendPage();
            mCurrentPageindex = mSpenNoteDoc.getPageIndexById(mSpenPageDoc.getId());
            mSpenPageDoc.setBackgroundColor(mOptions.getColor());
            mSpenPageDoc.clearHistory();
            mSpenSurfaceView.setPageDoc(mSpenPageDoc, true);

            mPenInfo = new SpenSettingPenInfo();
            mPenInfo.size = PEN_SIZE;
            mPenInfo.color = Color.BLUE;
            mPenInfo.name = PEN_TYPE;
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "popup mPenInfo:" + mPenInfo.name);
            }
            mSpenSurfaceView.setPenSettingInfo(mPenInfo);

            LayoutParams p = new LayoutParams(point.x, point.y);

            // Adding Basic colors
            resId = activity.getResources().getIdentifier("spentraybar_basic_colors", "layout",
                    activity.getPackageName());
            LinearLayout basic_colors = (LinearLayout) View.inflate(activity, resId, null);
            lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.addRule(RelativeLayout.BELOW, traybar_top.getId());
            mRelativeLayout.addView(basic_colors, lp);

            mDialog.setContentView(mRelativeLayout, p);
            setBgImage(mOptions);
            mDialog.show();
        } catch (SsdkUnsupportedException e) {
            Log.d(TAG, "failed initializing the spen package " + e.getMessage());
            e.printStackTrace();
            PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, e.getType());
            pluginResult.setKeepCallback(false);
            mContextParams.getCallbackContext().sendPluginResult(pluginResult);
            closeSurfaceControls();
            isSurface = false;
        } catch (IOException e) {
            Log.d(TAG, "cannot create new doc: " + e.getMessage());
            e.printStackTrace();
            SpenException.sendPluginResult(SpenExceptionType.FAILED_CREATE_SURFACE,
                    mContextParams.getCallbackContext());
            closeSurfaceControls();
            isSurface = false;
        } catch (OutOfMemoryError e) {
            Runtime runtime = Runtime.getRuntime();
            Log.d(TAG, "Memory Usage, Memory Used: " + runtime.totalMemory() + " , Max Memory: "
                    + runtime.maxMemory());
            e.printStackTrace();
            closeSurfaceControls();
            SpenException.sendPluginResult(SpenExceptionType.MAX_HEAP_MEMORY_REACHED,
                    mContextParams.getCallbackContext());
            isSurface = false;
        }

        mOrientationListener = new OrientationEventListener(activity.getApplicationContext()) {
            int orntation = Configuration.ORIENTATION_PORTRAIT;

            @Override
            public void onOrientationChanged(int orientation) {
                Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
                if (orntation != activity.getResources().getConfiguration().orientation) {
                    if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                        Log.d(TAG, "onOrientationChanged() called");
                    }
                    orntation = activity.getResources().getConfiguration().orientation;
                    Message msgObj = handler.obtainMessage();
                    Bundle b = new Bundle();
                    b.putInt("orientation", orntation);
                    msgObj.setData(b);
                    handler.sendMessage(msgObj);
                }
            }
        };

        if (mOrientationListener.canDetectOrientation() == true) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "Can detect orientation");
            }
            mOrientationListener.enable();
        }
        return isSurface;
    }

    /**
     * Compare default Height and Width with Spen Page Doc size and return the minimum Height and Width
     * 
     * @return size Point
     * 
     */
    private Point getWidthAndHeightOnOrientation() {
        Point size = new Point();
        int defaultWidth = getDefaultWidth();
        if (mPageDocSizes.x > defaultWidth) {
            size.x = defaultWidth;
        } else {
            size.x = mPageDocSizes.x;
        }
        int defaultHeight = getDefaultHeight();
        if (mPageDocSizes.y > defaultHeight) {
            size.y = defaultHeight;
        } else {
            size.y = mPageDocSizes.y;
        }
        return size;
    }

    /**
     * Get Height and Width for Spen Page Doc
     * 
     * @return size of Spen Page Doc
     * 
     */
    private Point getWidthAndHeightForPageDoc() {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside getDimensionsforPageDoc");
        }
        Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
        Display display = activity.getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "getDimensionsforPageDoc device dimensions are: " + size.x + " " + size.y);
        }
        size = findWidthAndHeightForPageDoc(size);
        size.y = size.y + (int) (((float) 24) * activity.getResources().getDisplayMetrics().density);
        return size;
    }

    /**
     * Find Height and Width for Spen Page Doc
     * 
     * @params size
     *            Point
     * @return width and height of Page Doc
     * 
     */

    private Point findWidthAndHeightForPageDoc(Point size) {
        Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
        Context context = activity.getApplicationContext();
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "inside findWidthAndHeightForPageDoc");
        }
        int actualWidth = mOptions.getSurfacePosition().getWidth();
        int actualHeight = mOptions.getSurfacePosition().getHeight();
        boolean isWidthValid = mOptions.getSurfacePosition().isValidWidth(mOptions, context);
        boolean isHeightValid = mOptions.getSurfacePosition().isValidHeight(mOptions, context);
        int minWidth = mOptions.getMinWidth();
        int minHeight = mOptions.getMinHeight();
        int defaultWidth = SurfacePosition.getMaxWidth(context);
        int defaultHeight = SurfacePosition.getMaxHeight(context);

        ImageUriVO vo = getImageUriVO();
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "actual width and height: " + actualWidth + " " + actualHeight);
            Log.d(TAG, "are width and height valid: " + isWidthValid + " " + isHeightValid);
            Log.d(TAG, "min width and height: " + minWidth + " " + minHeight);
            Log.d(TAG, "default width and height: " + defaultWidth + " " + defaultHeight);
            Log.d(TAG, "ImageUri width and height: " + vo.getWidth() + " " + vo.getHeight());
            Log.d(TAG, "ImageUri valid: " + vo.isValid());
        }
        // there are combination of 3 bits and a total of 8
        // possible cases
        // assume width is bit 2, height is bit 1, uri is bit 0
        if (isWidthValid & isHeightValid) { // covers 110 & 111
            // show surface with default width n height
            Log.d(TAG, "width and height are valid");
            size.x = actualWidth;
            size.y = actualHeight;
        } else if (isWidthValid & !isHeightValid) {
            size.x = actualWidth;
            if (vo.isValid()) { // covers 101
                Log.d(TAG, "width and image Uri are valid");
                // calculate height according to imageuri aspect ratio
                size.y = (vo.getHeight() * actualWidth) / vo.getWidth();
                if (size.y > defaultHeight) {
                    Log.d(TAG, "height not satisfying constraints. defaulting..");
                    size.y = defaultHeight;
                } else if (size.y < minHeight) {
                    Log.d(TAG, "height not satisfying constraints. Setting minimum height..");
                    size.y = minHeight;
                }
            } else { // covers 100
                Log.d(TAG, "only width is valid");
                // assign default height
                Log.d(TAG, "height not satisfying constraints. defaulting..");
                size.y = defaultHeight;
            }
        } else if (!isWidthValid & isHeightValid) {
            size.y = actualHeight;
            if (vo.isValid()) { // covers 011
                Log.d(TAG, "height and image uri are valid");
                // calculate width according to imageuri aspect ratio
                size.x = (vo.getWidth() * actualHeight) / vo.getHeight();
                if (size.x > defaultWidth) {
                    Log.d(TAG, "width not satisfying constraints. defaulting..");
                    size.x = defaultWidth;
                }
                if (size.x < minWidth) {
                    Log.d(TAG, "width not satisfying constraints. Setting min width");
                    size.x = minWidth;
                }
            } else { // covers 010
                Log.d(TAG, "only height is valid");
                Log.d(TAG, "width not satisfying constraints. defaulting..");
                // assign default width
                size.x = defaultWidth;
            }
        } else if (vo.isValid()) { // covers 001
            Log.d(TAG, "only image uri valid");
            float deviceRatio = (float) defaultHeight / (float) defaultWidth;
            float imageRatio = (float) vo.getHeight() / (float) vo.getWidth();
            if (deviceRatio < imageRatio) {
                int height = defaultHeight < vo.getHeight() ? defaultHeight : vo.getHeight();
                if (height < minHeight) {
                    height = minHeight;
                }
                int width = (int) (height / imageRatio);
                if (width < minWidth) {
                    Log.d(TAG, "width not satisfying constraints2. Setting min width");
                    width = minWidth;
                }
                size.y = height;
                size.x = width;
            } else {
                int width = defaultWidth < vo.getWidth() ? defaultWidth : vo.getWidth();
                if (width < minWidth) {
                    width = minWidth;
                }
                int height = (int) (width * imageRatio);
                if (height < minHeight) {
                    height = minHeight;
                    Log.d(TAG, "height not satisfying constraints2. Setting min height");
                }
                size.x = width;
                size.y = height;
            }
        } else { // covers 000
            Log.d(TAG, "all image uri, width & height are invalid");
            size.x = defaultWidth;
            size.y = defaultHeight;
        }
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "width and height are : " + size.x + " " + size.y);
        }
        return size;
    }

    /**
     * Calculate Default Height in portrait and landscape mode to avoid display issues
     * 
     * @return Height
     * 
     */
    private int getDefaultHeight() {
        Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
        DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
        // restricting the max display to 90%
        // to avoid display issues
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            return (int) (Utils.PORTRAIT_Y_FACTOR * metrics.heightPixels);
        } else {
            return (int) (Utils.LANDSCAPE_Y_FACTOR * metrics.heightPixels);
        }
    }

    /**
     * Get Default Width
     * 
     * @return  width
     * 
     */
    public int getDefaultWidth() {
        Activity activity = mContextParams.getSpenCustomDrawPlugin().cordova.getActivity();
        DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
        // restricting the max display to 90%
        // to avoid display issues
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            return (int) (Utils.PORTRAIT_X_FACTOR * metrics.widthPixels);
        } else {
            return (int) (Utils.LANDSCAPE_X_FACTOR * metrics.widthPixels);
        }
    }

    /**
     * Clear History of Spen Page Doc
     * 
     */
    void clearUndoRedo() {
        mSpenPageDoc.clearHistory();
    }

    /**
     * Open SPen Surface
     * 
     * @params options SpenTrayBarOptions
     * @params contextParams SpenContextParams
     */

    void openSpenSurface(SpenTrayBarOptions options, SpenContextParams contextParams) {
        mContextParams = contextParams;
        mOptions = options;
        setBgImage(mOptions);
        mDialog.show();
    }

    /**
     * Get Current Page Index
     * 
     *  @return mCurrentPageindex
     */
    int getCurrentPageindex() {
        return mCurrentPageindex;
    }

    /**
     * Set Current Page Index
     * 
     *  @params index
     *             mCurrentPageindex to be set
     * 
     */
    void setCurrentPageindex(int index) {
        mCurrentPageindex = index;
    }

    /**
     * 
     * Dismiss the dialog
     * 
     */

    void dismissDialog() {
        if (mDialog != null && mDialog.isShowing()) {
            mDialog.dismiss();
        }
    }

    /**
     * Handle Orientation
     * @params orientation
     */
    void handleOrientationChange(int orientation) {
        LayoutParams lp = null;
        if (mDialog != null) {
            if (mDialog.isShowing()) {
                mDialog.dismiss();
                mSpenSettingPenLayout.setPosition(0, 0);
                lp = new LayoutParams(getWidthAndHeightOnOrientation().x, getWidthAndHeightOnOrientation().y);
                mDialog.setContentView(mRelativeLayout, lp);
                mDialog.show();
            } else {
                lp = new LayoutParams(getWidthAndHeightOnOrientation().x, getWidthAndHeightOnOrientation().y);
                mDialog.setContentView(mRelativeLayout, lp);
            }
        }
        // dismissing and showing the discard dialog to
        // to align with the popup dialog
        if (mADiscardDialog != null && mADiscardDialog.isShowing()) {
            mADiscardDialog.dismiss();
            if (mDialog.isShowing()) {
                mADiscardDialog.show();
            }
        }
    }

    /**
     * remove surface and close controls
     *
     */
    public void removeSurface() {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d("TAG", "Inside removeSurface");
        }
        if (mDialog != null) {
            mDialog.dismiss();
        }
        mDialog = null;
        mSpenSettingPenLayout = null;
        mSelectionSettingView = null;
        closeSurfaceControls();
    }

    /**
     * Set SpenSettingLayout
     * 
     * @params penLayout SpenSettingPenLayout to be set
     */
    public void setSpenSettingPenLayout(SpenSettingPenLayout penLayout) {
        mSpenSettingPenLayout = penLayout;
    }

    /**
     * Set SpenSettingSelectionLayout
     * 
     * @params selectionLayout SpenSettingSelectionLayout to be set
     */
    public void SetSpenSettingSelectionLayout(SpenSettingSelectionLayout selectionLayout) {
        mSelectionSettingView = selectionLayout;
    }

    @Override
    void setAlertDialog(AlertDialog alertDialog) {
        mADiscardDialog = alertDialog;
    }
}