Example usage for android.graphics PointF PointF

List of usage examples for android.graphics PointF PointF

Introduction

In this page you can find the example usage for android.graphics PointF PointF.

Prototype

public PointF() 

Source Link

Usage

From source file:io.github.douglasjunior.androidSimpleTooltip.SimpleTooltip.java

private PointF calculePopupLocation() {
    PointF location = new PointF();

    final RectF anchorRect = calculeAnchorRect();
    final PointF anchorCenter = new PointF(anchorRect.centerX(), anchorRect.centerY());

    switch (mGravity) {
    case Gravity.START:
        location.x = anchorRect.left - mPopupWindow.getContentView().getWidth() - mMargin;
        location.y = anchorCenter.y - mPopupWindow.getContentView().getHeight() / 2f;
        break;/*from  w  ww . j  av a 2 s  . co m*/
    case Gravity.END:
        location.x = anchorRect.right + mMargin;
        location.y = anchorCenter.y - mPopupWindow.getContentView().getHeight() / 2f;
        break;
    case Gravity.TOP:
        location.x = anchorCenter.x - mPopupWindow.getContentView().getWidth() / 2f;
        location.y = anchorRect.top - mPopupWindow.getContentView().getHeight() - mMargin;
        break;
    case Gravity.BOTTOM:
        location.x = anchorCenter.x - mPopupWindow.getContentView().getWidth() / 2f;
        location.y = anchorRect.bottom + mMargin;
        break;
    default:
        throw new IllegalArgumentException("Gravity must have be START, END, TOP or BOTTOM.");
    }

    return location;
}

From source file:com.alburivan.slickform.tooltip.SimpleTooltip.java

private PointF calculePopupLocation() {
    PointF location = new PointF();

    final RectF anchorRect = SimpleTooltipUtils.calculeRectInWindow(mAnchorView);
    final PointF anchorCenter = new PointF(anchorRect.centerX(), anchorRect.centerY());

    switch (mGravity) {
    case Gravity.START:
        location.x = anchorRect.left - mPopupWindow.getContentView().getWidth() - mMargin;
        location.y = anchorCenter.y - mPopupWindow.getContentView().getHeight() / 2f;
        break;// w w w  .  ja v  a 2s .  c om
    case Gravity.END:
        location.x = anchorRect.right + mMargin;
        location.y = anchorCenter.y - mPopupWindow.getContentView().getHeight() / 2f;
        break;
    case Gravity.TOP:
        location.x = anchorCenter.x - mPopupWindow.getContentView().getWidth() / 2f;
        location.y = anchorRect.top - mPopupWindow.getContentView().getHeight() - mMargin;
        break;
    case Gravity.BOTTOM:
        location.x = anchorCenter.x - mPopupWindow.getContentView().getWidth() / 2f;
        location.y = anchorRect.bottom + mMargin;
        break;
    default:
        throw new IllegalArgumentException("Gravity must have be START, END, TOP or BOTTOM.");
    }

    return location;
}

From source file:com.appunite.scroll.ScaleImageView.java

@SuppressWarnings("UnusedDeclaration")
public ScaleImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
    mMinEdge = viewConfiguration.getScaledEdgeSlop();

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScaleImageView, defStyle, defStyle);
    assert a != null;

    Drawable src = null;/*  www. j ava2s.  com*/
    try {
        mMinWidth = a.getDimensionPixelSize(R.styleable.ScaleImageView_android_minWidth, 0);
        mMinHeight = a.getDimensionPixelSize(R.styleable.ScaleImageView_android_minHeight, 0);
        src = a.getDrawable(R.styleable.ScaleImageView_android_src);
    } finally {
        a.recycle();
    }

    ScaleGestureDetector.OnScaleGestureListener scaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
        /**
         * This is the active focal point in terms of the viewport. Could be a local
         * variable but kept here to minimize per-frame allocations.
         */
        private PointF viewportFocus = new PointF();

        @Override
        public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
            final ViewParent parent = getParent();
            if (parent != null) {
                parent.requestDisallowInterceptTouchEvent(true);
            }
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
            float focusX = scaleGestureDetector.getFocusX();
            float focusY = scaleGestureDetector.getFocusY();
            float scaleFactor = scaleGestureDetector.getScaleFactor();
            float previousScale = mScale;
            mScale *= scaleFactor;

            doScale(focusX, focusY, scaleFactor);
            return true;
        }

    };
    GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {

            releaseEdgeEffects();
            mScroller.forceFinished(true);
            ViewCompat.postInvalidateOnAnimation(ScaleImageView.this);
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return performClick();
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            mZoomer.forceFinished(true);
            mZoomStartScale = mScale;
            mZoomFocalPoint.set(e.getX(), e.getY());
            mZoomer.startZoom(ZOOM_AMOUNT);
            ViewCompat.postInvalidateOnAnimation(ScaleImageView.this);
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            getRealTranslation(mTranslation, mRealTranslation);
            mRealTranslation.offset(-distanceX, -distanceY);
            getTranslation(mRealTranslation, mTranslation);

            computeMaxScrollSize(mMaxScrollBuffer);
            getImageRect(mRectF);
            float scrolledX = -mRectF.left;
            float scrolledY = -mRectF.top;
            boolean canScrollX = mRectF.left > mContentRect.left || mRectF.right < mContentRect.right;
            boolean canScrollY = mRectF.top > mContentRect.top || mRectF.bottom < mContentRect.bottom;
            validateTranslation();

            disallowParentInterceptWhenOnEdge(distanceX, distanceY);

            if (mScale > mMinScale) {
                if (canScrollX && scrolledX < 0) {
                    mEdgeEffectLeft.onPull(scrolledX / (float) mContentRect.width());
                    mEdgeEffectLeftActive = true;
                }
                if (canScrollY && scrolledY < 0) {
                    mEdgeEffectTop.onPull(scrolledY / (float) mContentRect.height());
                    mEdgeEffectTopActive = true;
                }
                if (canScrollX && scrolledX > mMaxScrollBuffer.x) {
                    mEdgeEffectRight.onPull((scrolledX - mMaxScrollBuffer.x) / (float) mContentRect.width());
                    mEdgeEffectRightActive = true;
                }
                if (canScrollY && scrolledY > mMaxScrollBuffer.y) {
                    mEdgeEffectBottom.onPull((scrolledY - mMaxScrollBuffer.y) / (float) mContentRect.height());
                    mEdgeEffectBottomActive = true;
                }
            }

            ViewCompat.postInvalidateOnAnimation(ScaleImageView.this);
            return true;
        }

        private void disallowParentInterceptWhenOnEdge(float directionX, float directionY) {
            final ViewParent parent = getParent();
            if (parent != null && (mAllowParentHorizontalScroll || mAllowParentVerticalScroll)) {
                getImageRect(mRectF);
                if (mAllowParentHorizontalScroll) {
                    if (directionX > 0 && Math.abs(mRectF.right - mContentRect.right) > mMinEdge) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                    if (directionX < 0 && Math.abs(mRectF.left - mContentRect.left) > mMinEdge) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                }
                if (mAllowParentVerticalScroll) {
                    if (directionY > 0 && Math.abs(mRectF.bottom - mContentRect.bottom) > mMinEdge) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                    if (directionY < 0 && Math.abs(mRectF.top - mContentRect.top) > mMinEdge) {
                        parent.requestDisallowInterceptTouchEvent(true);
                    }
                }
            }
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            disallowParentInterceptWhenOnEdge(velocityX, velocityY);
            fling((int) -velocityX, (int) -velocityY);
            return true;
        }
    };

    mScaleGestureDetector = new ScaleGestureDetector(context, scaleGestureListener);
    mGestureDetector = new GestureDetectorCompat(context, gestureListener);

    mScroller = new OverScroller(context);
    mZoomer = new Zoomer(context);

    // Sets up edge effects
    mEdgeEffectLeft = new EdgeEffectCompat(context);
    mEdgeEffectTop = new EdgeEffectCompat(context);
    mEdgeEffectRight = new EdgeEffectCompat(context);
    mEdgeEffectBottom = new EdgeEffectCompat(context);

    setSrcDrawable(src);
}

From source file:uk.co.senab.photup.model.PhotoUpload.java

public void detectPhotoTags(final Bitmap originalBitmap) {
    // If we've already done Face detection, don't do it again...
    if (mCompletedDetection) {
        return;//from   ww  w  . ja  va2  s  .  com
    }

    final OnFaceDetectionListener listener = mFaceDetectListener.get();
    if (null != listener) {
        listener.onFaceDetectionStarted(this);
    }

    final int bitmapWidth = originalBitmap.getWidth();
    final int bitmapHeight = originalBitmap.getHeight();

    Bitmap bitmap = originalBitmap;

    // The Face detector only accepts 565 bitmaps, so create one if needed
    if (Bitmap.Config.RGB_565 != bitmap.getConfig()) {
        bitmap = originalBitmap.copy(Bitmap.Config.RGB_565, false);
    }

    final FaceDetector detector = new FaceDetector(bitmapWidth, bitmapHeight,
            Constants.FACE_DETECTOR_MAX_FACES);
    final FaceDetector.Face[] faces = new FaceDetector.Face[Constants.FACE_DETECTOR_MAX_FACES];
    final int detectedFaces = detector.findFaces(bitmap, faces);

    // We must have created a converted 565 bitmap
    if (bitmap != originalBitmap) {
        bitmap.recycle();
        bitmap = null;
    }

    if (Flags.DEBUG) {
        Log.d(LOG_TAG, "Detected Faces: " + detectedFaces);
    }

    FaceDetector.Face face;
    final PointF point = new PointF();
    for (int i = 0, z = faces.length; i < z; i++) {
        face = faces[i];
        if (null != face) {
            if (Flags.DEBUG) {
                Log.d(LOG_TAG, "Detected Face with confidence: " + face.confidence());
            }
            face.getMidPoint(point);
            addPhotoTag(new PhotoTag(point.x, point.y, bitmapWidth, bitmapWidth));
        }
    }

    if (null != listener) {
        listener.onFaceDetectionFinished(this);
    }
    mFaceDetectListener = null;

    mCompletedDetection = true;
}

From source file:com.tooltip.Tooltip.java

private PointF calculateLocation() {
    PointF location = new PointF();

    final RectF anchorRect = Util.calculateRectInWindow(mAnchorView);
    final PointF anchorCenter = new PointF(anchorRect.centerX(), anchorRect.centerY());

    switch (mGravity) {
    case Gravity.START:
        location.x = anchorRect.left - mContentView.getWidth() - mMargin;
        location.y = anchorCenter.y - mContentView.getHeight() / 2f;
        break;//  www . ja va  2  s. c o  m
    case Gravity.END:
        location.x = anchorRect.right + mMargin;
        location.y = anchorCenter.y - mContentView.getHeight() / 2f;
        break;
    case Gravity.TOP:
        location.x = anchorCenter.x - mContentView.getWidth() / 2f;
        location.y = anchorRect.top - mContentView.getHeight() - mMargin;
        break;
    case Gravity.BOTTOM:
        location.x = anchorCenter.x - mContentView.getWidth() / 2f;
        location.y = anchorRect.bottom + mMargin;
        break;
    }

    return location;
}

From source file:com.pseudosurface.levels.template.SimulatorActivity.java

@Override
public boolean onTouchEvent(MotionEvent event) {

    float x = event.getX();
    float y = event.getY();

    // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        start.set(event.getX(), event.getY());
        //          Log.d(TAG, "mode=DRAG");

        break;/*w ww.  j  a  v  a 2 s.  co m*/
    case MotionEvent.ACTION_POINTER_DOWN:
        oldDist = spacing(event);
        if (oldDist > 10f) {
            midPoint(mid, event);
            mode = ZOOM;
            //             Log.d(TAG, "mode=ZOOM");
        }
        break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
        mode = NONE;
        oldDist = -1;
        //          Log.d(TAG, "mode=NONE");
        break;
    case MotionEvent.ACTION_MOVE:

        if (mode == ZOOM) {
            float newDist = spacing(event);
            if (newDist > simulation.minZoom && oldDist != -1) {
                simulation.zoom -= (newDist - oldDist) * .05;
            }
            oldDist = newDist;
        } else {
            float dz = x - mPreviousX;
            float dy = y - mPreviousY;

            float r = (float) Math.sqrt(dz * dz + dy * dy);

            double theta = Math.atan2(dy, dz) + Math.PI + SimulatorActivity.angleLR;

            try {
                simulation.world.objects[simulation.world.getPlayerIndex()].omega[0] += .05f * r
                        * Math.cos(theta);
                simulation.world.objects[simulation.world.getPlayerIndex()].omega[2] += .05f * r
                        * Math.sin(theta);
            } catch (Exception e) {
            }

            //MainActivity.angleLR += dx*.01;
            //simulation.zoom += dy*.01;
        }
        break;
    }

    mPreviousX = x;
    mPreviousY = y;

    gestureDetector.onTouchEvent(event);

    return true; // indicate event was handled
}

From source file:edu.ptu.navpattern.tooltip.Tooltip.java

private PointF calculateLocation() {
    PointF location = new PointF();

    final RectF anchorRect = calculateRectInWindow(mAnchorView);
    final PointF anchorCenter = new PointF(anchorRect.centerX(), anchorRect.centerY());

    switch (mGravity) {
    case Gravity.START:
        location.x = anchorRect.left - mContentView.getWidth() - mMargin;
        location.y = anchorCenter.y - mContentView.getHeight() / 2f;
        break;//from  ww  w  .jav a2s .  com
    case Gravity.END:
        location.x = anchorRect.right + mMargin;
        location.y = anchorCenter.y - mContentView.getHeight() / 2f;
        break;
    case Gravity.TOP:
        location.x = anchorCenter.x - mContentView.getWidth() / 2f;
        location.y = anchorRect.top - mContentView.getHeight() - mMargin;
        break;
    case Gravity.BOTTOM:
        location.x = anchorCenter.x - mContentView.getWidth() / 2f;
        location.y = anchorRect.bottom + mMargin;
        break;
    }

    return location;
}

From source file:org.akop.crosswords.view.CrosswordView.java

public CrosswordView(Context context, AttributeSet attrs) {
    super(context, attrs);

    if (!isInEditMode()) {
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }//from  w w w .ja  v  a 2 s .c  om

    // Set drawing defaults
    Resources r = context.getResources();
    DisplayMetrics dm = r.getDisplayMetrics();

    int cellFillColor = NORMAL_CELL_FILL_COLOR;
    int cheatedCellFillColor = CHEATED_CELL_FILL_COLOR;
    int mistakeCellFillColor = MISTAKE_CELL_FILL_COLOR;
    int selectedWordFillColor = SELECTED_WORD_FILL_COLOR;
    int selectedCellFillColor = SELECTED_CELL_FILL_COLOR;
    int textColor = TEXT_COLOR;
    int cellStrokeColor = CELL_STROKE_COLOR;
    int circleStrokeColor = CIRCLE_STROKE_COLOR;

    float numberTextSize = NUMBER_TEXT_SIZE * dm.scaledDensity;
    float answerTextSize = ANSWER_TEXT_SIZE * dm.scaledDensity;

    mCellSize = CELL_SIZE * dm.density;
    mNumberTextPadding = NUMBER_TEXT_PADDING * dm.density;
    mAnswerTextPadding = ANSWER_TEXT_PADDING * dm.density;

    // Read supplied attributes
    if (attrs != null) {
        Resources.Theme theme = context.getTheme();
        TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.Crossword, 0, 0);
        mCellSize = a.getDimension(R.styleable.Crossword_cellSize, mCellSize);
        mNumberTextPadding = a.getDimension(R.styleable.Crossword_numberTextPadding, mNumberTextPadding);
        numberTextSize = a.getDimension(R.styleable.Crossword_numberTextSize, numberTextSize);
        mAnswerTextPadding = a.getDimension(R.styleable.Crossword_answerTextPadding, mAnswerTextPadding);
        answerTextSize = a.getDimension(R.styleable.Crossword_answerTextSize, answerTextSize);
        cellFillColor = a.getColor(R.styleable.Crossword_defaultCellFillColor, cellFillColor);
        cheatedCellFillColor = a.getColor(R.styleable.Crossword_cheatedCellFillColor, cheatedCellFillColor);
        mistakeCellFillColor = a.getColor(R.styleable.Crossword_mistakeCellFillColor, mistakeCellFillColor);
        selectedWordFillColor = a.getColor(R.styleable.Crossword_selectedWordFillColor, selectedWordFillColor);
        selectedCellFillColor = a.getColor(R.styleable.Crossword_selectedCellFillColor, selectedCellFillColor);
        cellStrokeColor = a.getColor(R.styleable.Crossword_cellStrokeColor, cellStrokeColor);
        circleStrokeColor = a.getColor(R.styleable.Crossword_circleStrokeColor, circleStrokeColor);
        textColor = a.getColor(R.styleable.Crossword_textColor, textColor);
        a.recycle();
    }

    mMarkerSideLength = mCellSize * MARKER_TRIANGLE_LENGTH_FRACTION;

    // Init paints
    mCellFillPaint = new Paint();
    mCellFillPaint.setColor(cellFillColor);
    mCellFillPaint.setStyle(Paint.Style.FILL);

    mCheatedCellFillPaint = new Paint();
    mCheatedCellFillPaint.setColor(cheatedCellFillColor);
    mCheatedCellFillPaint.setStyle(Paint.Style.FILL);

    mMistakeCellFillPaint = new Paint();
    mMistakeCellFillPaint.setColor(mistakeCellFillColor);
    mMistakeCellFillPaint.setStyle(Paint.Style.FILL);

    mSelectedWordFillPaint = new Paint();
    mSelectedWordFillPaint.setColor(selectedWordFillColor);
    mSelectedWordFillPaint.setStyle(Paint.Style.FILL);

    mSelectedCellFillPaint = new Paint();
    mSelectedCellFillPaint.setColor(selectedCellFillColor);
    mSelectedCellFillPaint.setStyle(Paint.Style.FILL);

    mCellStrokePaint = new Paint();
    mCellStrokePaint.setColor(cellStrokeColor);
    mCellStrokePaint.setStyle(Paint.Style.STROKE);
    //      mCellStrokePaint.setStrokeWidth(1);

    mCircleStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mCircleStrokePaint.setColor(circleStrokeColor);
    mCircleStrokePaint.setStyle(Paint.Style.STROKE);
    mCircleStrokePaint.setStrokeWidth(1);

    mNumberTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mNumberTextPaint.setColor(textColor);
    mNumberTextPaint.setTextAlign(Paint.Align.CENTER);
    mNumberTextPaint.setTextSize(numberTextSize);

    mNumberStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mNumberStrokePaint.setColor(cellFillColor);
    mNumberStrokePaint.setTextAlign(Paint.Align.CENTER);
    mNumberStrokePaint.setTextSize(numberTextSize);
    mNumberStrokePaint.setStyle(Paint.Style.STROKE);
    mNumberStrokePaint.setStrokeWidth(NUMBER_TEXT_STROKE_WIDTH * dm.scaledDensity);

    mAnswerTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mAnswerTextPaint.setColor(textColor);
    mAnswerTextPaint.setTextSize(answerTextSize);
    mAnswerTextPaint.setTextAlign(Paint.Align.CENTER);

    // http://www.google.com/fonts/specimen/Kalam
    Typeface typeface = Typeface.createFromAsset(context.getAssets(), "kalam-regular.ttf");
    mAnswerTextPaint.setTypeface(typeface);

    // Init rest of the values
    mCircleRadius = (mCellSize / 2) - mCircleStrokePaint.getStrokeWidth();
    mPuzzleCells = EMPTY_CELLS;
    mPuzzleWidth = 0;
    mPuzzleHeight = 0;
    mAllowedChars = EMPTY_CHARS;

    mRenderScale = 0;
    mBitmapOffset = new PointF();
    mCenteredOffset = new PointF();
    mTranslationBounds = new RectF();

    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    mGestureDetector = new GestureDetector(context, new GestureListener());

    mContentRect = new RectF();
    mPuzzleRect = new RectF();

    mBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);

    mScroller = new Scroller(context, null, true);
    mZoomer = new Zoomer(context);

    setFocusableInTouchMode(true);
    setOnKeyListener(this);
}

From source file:org.protocoderrunner.apprunner.api.PUI.java

public void draggable(View v) {
    v.setOnTouchListener(new OnTouchListener() {
        PointF downPT = new PointF(); // Record Mouse Position When Pressed
        // Down/*ww  w  .ja va2s  .com*/
        PointF startPT = new PointF(); // Record Start Position of 'img'

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int eid = event.getAction();
            switch (eid) {
            case MotionEvent.ACTION_MOVE:
                PointF mv = new PointF(event.getX() - downPT.x, event.getY() - downPT.y);
                v.setX((int) (startPT.x + mv.x));
                v.setY((int) (startPT.y + mv.y));
                startPT = new PointF(v.getX(), v.getY());
                break;
            case MotionEvent.ACTION_DOWN:
                downPT.x = event.getX();
                downPT.y = event.getY();
                startPT = new PointF(v.getX(), v.getY());
                break;
            case MotionEvent.ACTION_UP:
                // Nothing have to do
                break;
            default:
                break;
            }
            return true;
        }
    });

}

From source file:org.akop.ararat.view.CrosswordView.java

public CrosswordView(Context context, AttributeSet attrs) {
    super(context, attrs);

    if (!isInEditMode()) {
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }//from   w w  w .  j  a va  2 s  .c o  m

    // Set drawing defaults
    Resources r = context.getResources();
    DisplayMetrics dm = r.getDisplayMetrics();

    int cellFillColor = NORMAL_CELL_FILL_COLOR;
    int cheatedCellFillColor = CHEATED_CELL_FILL_COLOR;
    int mistakeCellFillColor = MISTAKE_CELL_FILL_COLOR;
    int selectedWordFillColor = SELECTED_WORD_FILL_COLOR;
    int selectedCellFillColor = SELECTED_CELL_FILL_COLOR;
    int markedCellFillColor = MARKED_CELL_FILL_COLOR;
    int numberTextColor = NUMBER_TEXT_COLOR;
    int cellStrokeColor = CELL_STROKE_COLOR;
    int circleStrokeColor = CIRCLE_STROKE_COLOR;
    int answerTextColor = ANSWER_TEXT_COLOR;

    mScaledDensity = dm.scaledDensity;
    float numberTextSize = NUMBER_TEXT_SIZE * mScaledDensity;
    mAnswerTextSize = ANSWER_TEXT_SIZE * mScaledDensity;

    mCellSize = CELL_SIZE * dm.density;
    mNumberTextPadding = NUMBER_TEXT_PADDING * dm.density;
    mIsEditable = true;
    mInputMode = INPUT_MODE_KEYBOARD;
    mSkipOccupiedOnType = false;
    mSelectFirstUnoccupiedOnNav = true;
    mMaxBitmapSize = DEFAULT_MAX_BITMAP_DIMENSION;

    // Read supplied attributes
    if (attrs != null) {
        Resources.Theme theme = context.getTheme();
        TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CrosswordView, 0, 0);

        mCellSize = a.getDimension(R.styleable.CrosswordView_cellSize, mCellSize);
        mNumberTextPadding = a.getDimension(R.styleable.CrosswordView_numberTextPadding, mNumberTextPadding);
        numberTextSize = a.getDimension(R.styleable.CrosswordView_numberTextSize, numberTextSize);
        mAnswerTextSize = a.getDimension(R.styleable.CrosswordView_answerTextSize, mAnswerTextSize);
        answerTextColor = a.getColor(R.styleable.CrosswordView_answerTextColor, answerTextColor);
        cellFillColor = a.getColor(R.styleable.CrosswordView_defaultCellFillColor, cellFillColor);
        cheatedCellFillColor = a.getColor(R.styleable.CrosswordView_cheatedCellFillColor, cheatedCellFillColor);
        mistakeCellFillColor = a.getColor(R.styleable.CrosswordView_mistakeCellFillColor, mistakeCellFillColor);
        selectedWordFillColor = a.getColor(R.styleable.CrosswordView_selectedWordFillColor,
                selectedWordFillColor);
        selectedCellFillColor = a.getColor(R.styleable.CrosswordView_selectedCellFillColor,
                selectedCellFillColor);
        markedCellFillColor = a.getColor(R.styleable.CrosswordView_markedCellFillColor, markedCellFillColor);
        cellStrokeColor = a.getColor(R.styleable.CrosswordView_cellStrokeColor, cellStrokeColor);
        circleStrokeColor = a.getColor(R.styleable.CrosswordView_circleStrokeColor, circleStrokeColor);
        numberTextColor = a.getColor(R.styleable.CrosswordView_numberTextColor, numberTextColor);
        mIsEditable = a.getBoolean(R.styleable.CrosswordView_editable, mIsEditable);
        mSkipOccupiedOnType = a.getBoolean(R.styleable.CrosswordView_skipOccupiedOnType, mSkipOccupiedOnType);
        mSelectFirstUnoccupiedOnNav = a.getBoolean(R.styleable.CrosswordView_selectFirstUnoccupiedOnNav,
                mSelectFirstUnoccupiedOnNav);

        a.recycle();
    }

    mRevealSetsCheatFlag = true;
    mMarkerSideLength = mCellSize * MARKER_TRIANGLE_LENGTH_FRACTION;

    // Init paints
    mCellFillPaint = new Paint();
    mCellFillPaint.setColor(cellFillColor);
    mCellFillPaint.setStyle(Paint.Style.FILL);

    mCheatedCellFillPaint = new Paint();
    mCheatedCellFillPaint.setColor(cheatedCellFillColor);
    mCheatedCellFillPaint.setStyle(Paint.Style.FILL);

    mMistakeCellFillPaint = new Paint();
    mMistakeCellFillPaint.setColor(mistakeCellFillColor);
    mMistakeCellFillPaint.setStyle(Paint.Style.FILL);

    mSelectedWordFillPaint = new Paint();
    mSelectedWordFillPaint.setColor(selectedWordFillColor);
    mSelectedWordFillPaint.setStyle(Paint.Style.FILL);

    mSelectedCellFillPaint = new Paint();
    mSelectedCellFillPaint.setColor(selectedCellFillColor);
    mSelectedCellFillPaint.setStyle(Paint.Style.FILL);

    mMarkedCellFillPaint = new Paint();
    mMarkedCellFillPaint.setColor(markedCellFillColor);
    mMarkedCellFillPaint.setStyle(Paint.Style.FILL);

    mCellStrokePaint = new Paint();
    mCellStrokePaint.setColor(cellStrokeColor);
    mCellStrokePaint.setStyle(Paint.Style.STROKE);
    //      mCellStrokePaint.setStrokeWidth(1);

    mCircleStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mCircleStrokePaint.setColor(circleStrokeColor);
    mCircleStrokePaint.setStyle(Paint.Style.STROKE);
    mCircleStrokePaint.setStrokeWidth(1);

    mNumberTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mNumberTextPaint.setColor(numberTextColor);
    mNumberTextPaint.setTextAlign(Paint.Align.CENTER);
    mNumberTextPaint.setTextSize(numberTextSize);

    // Compute number height
    mNumberTextPaint.getTextBounds("0", 0, "0".length(), mTempRect);
    mNumberTextHeight = mTempRect.height();

    mNumberStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mNumberStrokePaint.setColor(cellFillColor);
    mNumberStrokePaint.setTextAlign(Paint.Align.CENTER);
    mNumberStrokePaint.setTextSize(numberTextSize);
    mNumberStrokePaint.setStyle(Paint.Style.STROKE);
    mNumberStrokePaint.setStrokeWidth(NUMBER_TEXT_STROKE_WIDTH * mScaledDensity);

    mAnswerTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mAnswerTextPaint.setColor(answerTextColor);
    mAnswerTextPaint.setTextSize(mAnswerTextSize);

    // Init rest of the values
    mCircleRadius = (mCellSize / 2) - mCircleStrokePaint.getStrokeWidth();
    mPuzzleCells = EMPTY_CELLS;
    mPuzzleWidth = 0;
    mPuzzleHeight = 0;
    mAllowedChars = EMPTY_CHARS;

    mRenderScale = 0;
    mBitmapOffset = new PointF();
    mCenteredOffset = new PointF();
    mTranslationBounds = new RectF();

    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    mGestureDetector = new GestureDetector(context, new GestureListener());

    mContentRect = new RectF();
    mPuzzleRect = new RectF();

    mBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);

    mScroller = new Scroller(context, null, true);
    mZoomer = new Zoomer(context);
    mUndoBuffer = new Stack<>();

    setFocusableInTouchMode(mIsEditable && mInputMode != INPUT_MODE_NONE);
    setOnKeyListener(this);
}