text:
package com.wooplr.spotlight;

import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PathEffect;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.wooplr.spotlight.prefs.PreferencesManager;
import com.wooplr.spotlight.shape.Circle;
import com.wooplr.spotlight.shape.NormalLineAnimDrawable;
import com.wooplr.spotlight.target.AnimPoint;
import com.wooplr.spotlight.target.Target;
import com.wooplr.spotlight.target.ViewTarget;
import com.wooplr.spotlight.utils.SpotlightListener;
import com.wooplr.spotlight.utils.Utils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by jitender on 10/06/16.
 */

public class SpotlightView extends FrameLayout {

    /**
     * OverLay color
     */
    private int maskColor = 0x70000000;

    /**
     * Intro Animation Duration
     */
    private long introAnimationDuration = 400;

    /**
     * Toggel between reveal and fadein animation
     */
    private boolean isRevealAnimationEnabled = true;

    /**
     * Final fadein text duration
     */
    private long fadingTextDuration = 400;

    /**
     * Start intro once view is ready to show
     */
    private boolean isReady;

    /**
     * Overlay circle above the view
     */
    private Circle circleShape;

    /**
     * Target View
     */
    private Target targetView;

    /**
     * Eraser to erase the circle area
     */
    private Paint eraser;

    /**
     * Delay the intro view
     */
    private Handler handler;
    private Bitmap bitmap;
    private Canvas canvas;

    /**
     * Padding for circle
     */
    private int padding = 20;

    /**
     * View Width
     */
    private int width;

    /**
     * View Height
     */
    private int height;

    /**
     * Dismiss layout on touch
     */
    private boolean dismissOnTouch;
    private boolean dismissOnBackPress;
    private boolean enableDismissAfterShown;

    private PreferencesManager preferencesManager;
    private String usageId;

    /**
     * Listener for spotLight when user clicks on the view
     */
    private SpotlightListener listener;

    /**
     * Perform click when user clicks on the targetView
     */
    private boolean isPerformClick;

    /**
     * Margin from left, right, top and bottom till the line will stop
     */
    private int gutter = Utils.dpToPx(36);

    /**
     * Views Heading and sub-heading for spotlight
     */
    private TextView subHeadingTv, headingTv;

    /**
     * Whether to show the arc at the end of the line that points to the target.
     */
    private boolean showTargetArc = true;

    /**
     * Extra padding around the arc
     */
    private int extraPaddingForArc = 24;

    /**
     * Defaults for heading TextView
     */
    private int headingTvSize = 24;
    private int headingTvSizeDimenUnit = -1;
    private int headingTvColor = Color.parseColor("#eb273f");
    private CharSequence headingTvText = "Hello";

    /**
     * Defaults for sub-heading TextView
     */
    private int subHeadingTvSize = 24;
    private int subHeadingTvSizeDimenUnit = -1;
    private int subHeadingTvColor = Color.parseColor("#ffffff");
    private CharSequence subHeadingTvText = "Hello";

    /**
     * Values for line animation
     */
    private long lineAnimationDuration = 300;
    private int lineStroke;
    private PathEffect lineEffect;
    private int lineAndArcColor = Color.parseColor("#eb273f");

    private Typeface mTypeface = null;

    private int softwareBtnHeight;

    private boolean dismissCalled = false;

    public SpotlightView(Context context) {
        super(context);
        init(context);
    }

    public SpotlightView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public SpotlightView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SpotlightView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        setWillNotDraw(false);
        setVisibility(INVISIBLE);

        lineStroke = Utils.dpToPx(4);
        isReady = false;
        isRevealAnimationEnabled = true;
        dismissOnTouch = false;
        isPerformClick = false;
        enableDismissAfterShown = false;
        dismissOnBackPress = false;
        handler = new Handler();
        preferencesManager = new PreferencesManager(context);
        eraser = new Paint();
        eraser.setColor(0xFFFFFFFF);
        eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        eraser.setFlags(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getMeasuredWidth();
        height = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        try{
            if (!isReady) return;

            if (bitmap == null || canvas == null) {
                if (bitmap != null) bitmap.recycle();

                bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                this.canvas = new Canvas(bitmap);
            }

            this.canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            this.canvas.drawColor(maskColor);

            circleShape.draw(this.canvas, eraser, padding);

            canvas.drawBitmap(bitmap, 0, 0, null);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float xT = event.getX();
        float yT = event.getY();

        int xV = circleShape.getPoint().x;
        int yV = circleShape.getPoint().y;

        int radius = circleShape.getRadius();

        double dx = Math.pow(xT - xV, 2);
        double dy = Math.pow(yT - yV, 2);

        boolean isTouchOnFocus = (dx + dy) <= Math.pow(radius, 2);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                if (isTouchOnFocus && isPerformClick) {
                    targetView.getView().setPressed(true);
                    targetView.getView().invalidate();
                }

                return true;
            case MotionEvent.ACTION_UP:
                if (isTouchOnFocus || dismissOnTouch)
                    dismiss();

                if (isTouchOnFocus && isPerformClick) {
                    targetView.getView().performClick();
                    targetView.getView().setPressed(true);
                    targetView.getView().invalidate();
                    targetView.getView().setPressed(false);
                    targetView.getView().invalidate();
                }

                return true;
            default:
                break;
        }

        return super.onTouchEvent(event);
    }

    /**
     * Show the view based on the configuration
     * Reveal is available only for Lollipop and above in other only fadein will work
     * To support reveal in older versions use github.com/ozodrukh/CircularReveal
     *
     * @param activity
     */
    private void show(final Activity activity) {

        if (preferencesManager.isDisplayed(usageId))
            return;

        ((ViewGroup) activity.getWindow().getDecorView()).addView(this);

        setReady(true);

        handler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    try{
                                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

                                            if (isRevealAnimationEnabled)
                                                startRevealAnimation(activity);
                                            else {
                                                startFadinAnimation(activity);
                                            }
                                        } else {
                                            startFadinAnimation(activity);
                                        }
                                    }catch(Exception e){
                                        e.printStackTrace();
                                    }
                                }
                            }
                , 100);

    }

    /**
     * Dissmiss view with reverse animation
     */
    private void dismiss() {
        if (dismissCalled) {
            return;
        }
        dismissCalled = true;

        preferencesManager.setDisplayed(usageId);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (isRevealAnimationEnabled)
                exitRevealAnimation();
            else
                startFadeout();
        } else {
            startFadeout();
        }

    }

    /**
     * Revel animation from target center to screen width and height
     *
     * @param activity
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void startRevealAnimation(final Activity activity) {

        float finalRadius = (float) Math.hypot(getViewWidth(), getHeight());
        Animator anim = ViewAnimationUtils.createCircularReveal(this, targetView.getPoint().x, targetView.getPoint().y, 0, finalRadius);
        anim.setInterpolator(AnimationUtils.loadInterpolator(activity,
                android.R.interpolator.fast_out_linear_in));
        anim.setDuration(introAnimationDuration);

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                if (showTargetArc) {
                    addArcAnimation(activity);
                } else {
                    addPathAnimation(activity);
                }
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });

        setVisibility(View.VISIBLE);
        if (dismissOnBackPress) {
            requestFocus();
        }
        anim.start();
    }

    /**
     * Reverse reveal animation
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void exitRevealAnimation() {
        float finalRadius = (float) Math.hypot(getViewWidth(), getHeight());
        Animator anim = ViewAnimationUtils.createCircularReveal(this, targetView.getPoint().x, targetView.getPoint().y, finalRadius, 0);
        anim.setInterpolator(AnimationUtils.loadInterpolator(getContext(),
                android.R.interpolator.accelerate_decelerate));
        anim.setDuration(introAnimationDuration);

        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                setVisibility(GONE);
                removeSpotlightView();

            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });

        anim.start();
    }

    private void startFadinAnimation(final Activity activity) {
        AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
        fadeIn.setDuration(introAnimationDuration);
        fadeIn.setFillAfter(true);
        fadeIn.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (showTargetArc) {
                    addArcAnimation(activity);
                } else {
                    addPathAnimation(activity);
                }
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        setVisibility(VISIBLE);
        if (dismissOnBackPress) {
            requestFocus();
        }
        startAnimation(fadeIn);
    }

    private void startFadeout() {
        AlphaAnimation fadeIn = new AlphaAnimation(1.0f, 0.0f);
        fadeIn.setDuration(introAnimationDuration);
        fadeIn.setFillAfter(true);
        fadeIn.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                setVisibility(GONE);
                removeSpotlightView();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        startAnimation(fadeIn);

    }

    /**
     * Add arc above/below the circular target overlay.
     */
    private void addArcAnimation(final Activity activity) {
        AppCompatImageView mImageView = new AppCompatImageView(activity);
        mImageView.setImageResource(R.drawable.ic_spotlight_arc);
        LayoutParams params = new LayoutParams(2 * (circleShape.getRadius() + extraPaddingForArc),
                2 * (circleShape.getRadius() + extraPaddingForArc));

        if (targetView.getPoint().y > getHeight() / 2) {//bottom
            if (targetView.getPoint().x > getWidth() / 2) {//Right
                params.rightMargin = getWidth() - targetView.getPoint().x - circleShape.getRadius() - extraPaddingForArc;
                params.bottomMargin = getHeight() - targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc;
                params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
            } else {
                params.leftMargin = targetView.getPoint().x - circleShape.getRadius() - extraPaddingForArc;
                params.bottomMargin = getHeight() - targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc;
                params.gravity = Gravity.LEFT | Gravity.BOTTOM;
            }
        } else {//up
            mImageView.setRotation(180); //Reverse the view
            if (targetView.getPoint().x > getWidth() / 2) {//Right
                params.rightMargin = getWidth() - targetView.getPoint().x - circleShape.getRadius() - extraPaddingForArc;
                params.bottomMargin = getHeight() - targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc;
                params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
            } else {
                params.leftMargin = targetView.getPoint().x - circleShape.getRadius() - extraPaddingForArc;
                params.bottomMargin = getHeight() - targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc;
                params.gravity = Gravity.LEFT | Gravity.BOTTOM;
            }

        }
        mImageView.postInvalidate();
        mImageView.setLayoutParams(params);
        addView(mImageView);

        PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(lineAndArcColor,
                PorterDuff.Mode.SRC_ATOP);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            AnimatedVectorDrawable avd = (AnimatedVectorDrawable)
                    ContextCompat.getDrawable(activity, R.drawable.avd_spotlight_arc);
            avd.setColorFilter(porterDuffColorFilter);
            mImageView.setImageDrawable(avd);
            avd.start();
        } else {
            AnimatedVectorDrawableCompat avdc =
                    AnimatedVectorDrawableCompat.create(activity, R.drawable.avd_spotlight_arc);
            avdc.setColorFilter(porterDuffColorFilter);
            mImageView.setImageDrawable(avdc);
            avdc.start();
        }

        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                addPathAnimation(activity);
            }
        }, 400);
    }

    private void addPathAnimation(Activity activity) {

        View mView = new View(activity);
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        params.width = getViewWidth();
        params.height = getViewHeight();
//        params.width = getMeasuredWidth();
//        params.height = getMeasuredHeight();
        addView(mView, params);

        //Textviews
        headingTv = new TextView(activity);
        if (mTypeface != null)
            headingTv.setTypeface(mTypeface);

        if(headingTvSizeDimenUnit != -1)
            headingTv.setTextSize(headingTvSizeDimenUnit,headingTvSize);
        else
            headingTv.setTextSize(headingTvSize);

        headingTv.setVisibility(View.GONE);
        headingTv.setTextColor(headingTvColor);
        headingTv.setText(headingTvText);

        subHeadingTv = new TextView(activity);
        if (mTypeface != null)
            subHeadingTv.setTypeface(mTypeface);

        if(subHeadingTvSizeDimenUnit != -1)
            subHeadingTv.setTextSize(subHeadingTvSizeDimenUnit,subHeadingTvSize);
        else
            subHeadingTv.setTextSize(subHeadingTvSize);

        subHeadingTv.setTextColor(subHeadingTvColor);
        subHeadingTv.setVisibility(View.GONE);
        subHeadingTv.setText(subHeadingTvText);

        //Line animation
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setDither(true);
        p.setStyle(Paint.Style.STROKE);
        p.setStrokeJoin(Paint.Join.ROUND);
        p.setStrokeCap(Paint.Cap.ROUND);
        p.setStrokeWidth(lineStroke);
        p.setColor(lineAndArcColor);
        p.setPathEffect(lineEffect);

        NormalLineAnimDrawable animDrawable1 = new NormalLineAnimDrawable(p);
        if (lineAnimationDuration > 0)
            animDrawable1.setLineAnimDuration(lineAnimationDuration);
        if (Build.VERSION.SDK_INT < 16) {
            mView.setBackgroundDrawable(animDrawable1);
        } else {
            mView.setBackground(animDrawable1);
        }

        animDrawable1.setPoints(checkLinePoint());
        animDrawable1.playAnim();

        animDrawable1.setmListner(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                AlphaAnimation fadeIn = new AlphaAnimation(0.0f, 1.0f);
                fadeIn.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        if(enableDismissAfterShown)
                            dismissOnTouch = true;
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                fadeIn.setDuration(fadingTextDuration);
                fadeIn.setFillAfter(true);
                headingTv.startAnimation(fadeIn);
                subHeadingTv.startAnimation(fadeIn);
                headingTv.setVisibility(View.VISIBLE);
                subHeadingTv.setVisibility(View.VISIBLE);

            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });

    }

    private void enableDismissOnBackPress() {
        setFocusableInTouchMode(true);
        setFocusable(true);
        requestFocus();
    }

    private List<AnimPoint> checkLinePoint() {

        //Screen Height
        int screenWidth = getWidth();
        int screenHeight = getHeight();

        List<AnimPoint> animPoints = new ArrayList<>();

        //For TextViews
        LayoutParams headingParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        LayoutParams subHeadingParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);

        //Spaces above and below the line
        int spaceAboveLine = Utils.dpToPx(8);
        int spaceBelowLine = Utils.dpToPx(12);

        int extramargin = Utils.dpToPx(16);

        //check up or down
        if (targetView.getPoint().y > screenHeight / 2) {//Down TODO: add a logic for by 2
            if (targetView.getPoint().x > screenWidth / 2) {//Right
                animPoints.add(new AnimPoint((targetView.getViewRight() - targetView.getViewWidth() / 2),
                        targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc, (targetView.getViewRight() - targetView.getViewWidth() / 2),
                        targetView.getViewTop() / 2
                ));
                animPoints.add(new AnimPoint((targetView.getViewRight() - targetView.getViewWidth() / 2),
                        targetView.getViewTop() / 2,
                        gutter,
                        targetView.getViewTop() / 2));
                //TextViews
                headingParams.leftMargin = gutter;
                headingParams.rightMargin = screenWidth - (targetView.getViewRight() - targetView.getViewWidth() / 2) + extramargin;
                headingParams.bottomMargin = screenHeight - targetView.getViewTop() / 2 + spaceAboveLine;
                headingParams.topMargin = extramargin;
                headingParams.gravity = Gravity.BOTTOM | Gravity.LEFT;
                headingTv.setGravity(Gravity.LEFT);

                subHeadingParams.rightMargin = screenWidth - (targetView.getViewRight() - targetView.getViewWidth() / 2) + extramargin;
                subHeadingParams.leftMargin = gutter;
                subHeadingParams.bottomMargin = extramargin;
                subHeadingParams.topMargin = targetView.getViewTop() / 2 + spaceBelowLine;
                subHeadingParams.gravity = Gravity.LEFT;
                subHeadingTv.setGravity(Gravity.LEFT);

            } else {//left
                animPoints.add(new AnimPoint((targetView.getViewRight() - targetView.getViewWidth() / 2), targetView.getPoint().y - circleShape.getRadius() - extraPaddingForArc,
                        (targetView.getViewRight() - targetView.getViewWidth() / 2),
                        targetView.getViewTop() / 2
                ));

                animPoints.add(new AnimPoint((targetView.getViewRight() - targetView.getViewWidth() / 2),
                        targetView.getViewTop() / 2,
                        screenWidth - ((screenHeight > screenWidth) ? gutter : (gutter + softwareBtnHeight)),
                        targetView.getViewTop() / 2));

                //TextViews
                if(screenHeight > screenWidth)
                    headingParams.rightMargin = gutter;//portrait
                else
                    headingParams.rightMargin = gutter + softwareBtnHeight;//landscape
                headingParams.leftMargin = (targetView.getViewRight() - targetView.getViewWidth() / 2) + extramargin;
                headingParams.bottomMargin = screenHeight - targetView.getViewTop() / 2 + spaceAboveLine;
                headingParams.topMargin = extramargin;
                headingParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
                headingTv.setGravity(Gravity.LEFT);

                if(screenHeight > screenWidth)
                    subHeadingParams.rightMargin = gutter;//portrait
                else
                    subHeadingParams.rightMargin = gutter + softwareBtnHeight;//landscape
                subHeadingParams.leftMargin = (targetView.getViewRight() - targetView.getViewWidth() / 2) + extramargin;
                subHeadingParams.topMargin = targetView.getViewTop() / 2 + spaceBelowLine;
                subHeadingParams.bottomMargin = extramargin;
                subHeadingParams.gravity = Gravity.RIGHT;
                subHeadingTv.setGravity(Gravity.LEFT);

            }
        } else {//top
            if (targetView.getPoint().x > screenWidth / 2) {//Right
                animPoints.add(new AnimPoint(targetView.getViewRight() - targetView.getViewWidth() / 2,
                        targetView.getPoint().y + circleShape.getRadius() + extraPaddingForArc,
                        targetView.getViewRight() - targetView.getViewWidth() / 2,
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()));

                animPoints.add(new AnimPoint(targetView.getViewRight() - targetView.getViewWidth() / 2,
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom(),
                        gutter,
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()));

//                //TextViews
                headingParams.leftMargin = gutter;
                headingParams.rightMargin = screenWidth - (targetView.getViewRight() - targetView.getViewWidth() / 2) + extramargin;
                headingParams.bottomMargin = screenHeight - ((screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()) + spaceAboveLine;
                headingParams.topMargin = extramargin;
                headingParams.gravity = Gravity.BOTTOM | Gravity.LEFT;
                headingTv.setGravity(Gravity.LEFT);

                subHeadingParams.leftMargin = gutter;
                subHeadingParams.rightMargin = screenWidth - targetView.getViewRight() + targetView.getViewWidth() / 2 + extramargin;
                subHeadingParams.bottomMargin = extramargin;
                subHeadingParams.topMargin = ((screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()) + spaceBelowLine;
                subHeadingParams.gravity = Gravity.LEFT;
                subHeadingTv.setGravity(Gravity.LEFT);

            } else {//left
                animPoints.add(new AnimPoint(targetView.getViewRight() - targetView.getViewWidth() / 2,
                        targetView.getPoint().y + circleShape.getRadius() + extraPaddingForArc,
                        targetView.getViewRight() - targetView.getViewWidth() / 2,
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()));

                animPoints.add(new AnimPoint(targetView.getViewRight() - targetView.getViewWidth() / 2,
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom(),
                        screenWidth - ((screenHeight > screenWidth) ? gutter : (gutter + softwareBtnHeight)),
                        (screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()));

//                //TextViews
                if(screenHeight > screenWidth)
                    headingParams.rightMargin = gutter;//portrait
                else
                    headingParams.rightMargin = gutter + softwareBtnHeight;//landscape
                headingParams.leftMargin = targetView.getViewRight() - targetView.getViewWidth() / 2 + extramargin;
                headingParams.bottomMargin = screenHeight - ((screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()) + spaceAboveLine;
                headingParams.topMargin = extramargin;
                headingParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
                headingTv.setGravity(Gravity.LEFT);

                if(screenHeight > screenWidth)
                    subHeadingParams.rightMargin = gutter;//portrait
                else
                    subHeadingParams.rightMargin = gutter + softwareBtnHeight;//landscape
                subHeadingParams.leftMargin = targetView.getViewRight() - targetView.getViewWidth() / 2 + extramargin;
                subHeadingParams.bottomMargin = extramargin;
                subHeadingParams.topMargin = ((screenHeight - targetView.getViewBottom()) / 2 + targetView.getViewBottom()) + spaceBelowLine;
                subHeadingParams.gravity = Gravity.RIGHT;
                subHeadingTv.setGravity(Gravity.LEFT);
            }
        }

        addView(headingTv, headingParams);
        addView(subHeadingTv, subHeadingParams);

        return animPoints;
    }

    /**
     * Remove the spotlight view
     */
    private void removeSpotlightView() {

        if (listener != null)
            listener.onUserClicked(usageId);

        if (getParent() != null)
            ((ViewGroup) getParent()).removeView(this);
    }

    /**
     * Remove the spotlight view
     * @param needOnUserClickedCallback true, if user wants a call back when this spotlight view is removed from parent.
     */
    public void removeSpotlightView(boolean needOnUserClickedCallback) {
        try{
            if(needOnUserClickedCallback && listener != null)
                listener.onUserClicked(usageId);

            if (getParent() != null)
                ((ViewGroup) getParent()).removeView(this);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * Setters
     */

    public void setListener(SpotlightListener listener) {
        this.listener = listener;
    }

    private void setMaskColor(int maskColor) {
        this.maskColor = maskColor;
    }

    public void setReady(boolean ready) {
        isReady = ready;
    }

    public void setPadding(int padding) {
        this.padding = padding;
    }

    public void setDismissOnTouch(boolean dismissOnTouch) {
        this.dismissOnTouch = dismissOnTouch;
    }

    public void setDismissOnBackPress(boolean dismissOnBackPress) {
        this.dismissOnBackPress = dismissOnBackPress;
    }

    public boolean isEnableDismissAfterShown() {
        return enableDismissAfterShown;
    }

    public void setEnableDismissAfterShown(boolean enableDismissAfterShown) {
        this.enableDismissAfterShown = enableDismissAfterShown;
    }

    public void setPerformClick(boolean performClick) {
        isPerformClick = performClick;
    }

    public void setExtraPaddingForArc(int extraPaddingForArc) {
        this.extraPaddingForArc = extraPaddingForArc;
    }

    /**
     * Whether to show the arc under/above the circular target overlay.
     *
     * @param show Set to true to show the arc line, false otherwise.
     */
    public void setShowTargetArc(boolean show) {
        this.showTargetArc = show;
    }

    public void setIntroAnimationDuration(long introAnimationDuration) {
        this.introAnimationDuration = introAnimationDuration;
    }

    public void setRevealAnimationEnabled(boolean revealAnimationEnabled) {
        isRevealAnimationEnabled = revealAnimationEnabled;
    }

    public void setFadingTextDuration(long fadingTextDuration) {
        this.fadingTextDuration = fadingTextDuration;
    }

    public void setCircleShape(Circle circleShape) {
        this.circleShape = circleShape;
    }

    public void setTargetView(Target targetView) {
        this.targetView = targetView;
    }

    public void setUsageId(String usageId) {
        this.usageId = usageId;
    }

    public void setHeadingTvSize(int headingTvSize) {
        this.headingTvSize = headingTvSize;
    }

    public void setHeadingTvSize(int dimenUnit,int headingTvSize) {
        this.headingTvSizeDimenUnit = dimenUnit;
        this.headingTvSize = headingTvSize;
    }

    public void setHeadingTvColor(int headingTvColor) {
        this.headingTvColor = headingTvColor;
    }

    public void setHeadingTvText(CharSequence headingTvText) {
        this.headingTvText = headingTvText;
    }

    public void setSubHeadingTvSize(int subHeadingTvSize) {
        this.subHeadingTvSize = subHeadingTvSize;
    }

    public void setSubHeadingTvSize(int dimenUnit, int subHeadingTvSize) {
        this.subHeadingTvSizeDimenUnit = dimenUnit;
        this.subHeadingTvSize = subHeadingTvSize;
    }

    public void setSubHeadingTvColor(int subHeadingTvColor) {
        this.subHeadingTvColor = subHeadingTvColor;
    }

    public void setSubHeadingTvText(CharSequence subHeadingTvText) {
        this.subHeadingTvText = subHeadingTvText;
    }

    public void setLineAnimationDuration(long lineAnimationDuration) {
        this.lineAnimationDuration = lineAnimationDuration;
    }

    public void setLineAndArcColor(int lineAndArcColor) {
        this.lineAndArcColor = lineAndArcColor;
    }

    public void setLineStroke(int lineStroke) {
        this.lineStroke = lineStroke;
    }

    public void setLineEffect(PathEffect pathEffect) {
        this.lineEffect = pathEffect;
    }

    private void setSoftwareBtnHeight(int px){
        this.softwareBtnHeight = px;
    }

    public void setTypeface(Typeface typeface) {
        this.mTypeface = typeface;
    }

    public void setConfiguration(SpotlightConfig configuration) {

        if (configuration != null) {
            this.maskColor = configuration.getMaskColor();
            this.introAnimationDuration = configuration.getIntroAnimationDuration();
            this.isRevealAnimationEnabled = configuration.isRevealAnimationEnabled();
            this.fadingTextDuration = configuration.getFadingTextDuration();
            this.padding = configuration.getPadding();
            this.dismissOnTouch = configuration.isDismissOnTouch();
            this.dismissOnBackPress = configuration.isDismissOnBackpress();
            this.isPerformClick = configuration.isPerformClick();
            this.headingTvSize = configuration.getHeadingTvSize();
            this.headingTvSizeDimenUnit = configuration.getHeadingTvSizeDimenUnit();
            this.headingTvColor = configuration.getHeadingTvColor();
            this.headingTvText = configuration.getHeadingTvText();
            this.subHeadingTvSize = configuration.getSubHeadingTvSize();
            this.subHeadingTvSizeDimenUnit = configuration.getSubHeadingTvSizeDimenUnit();
            this.subHeadingTvColor = configuration.getSubHeadingTvColor();
            this.subHeadingTvText = configuration.getSubHeadingTvText();
            this.lineAnimationDuration = configuration.getLineAnimationDuration();
            this.lineStroke = configuration.getLineStroke();
            this.lineAndArcColor = configuration.getLineAndArcColor();
        }
    }

    /**
     * Builder Class
     */
    public static class Builder {

        private SpotlightView spotlightView;

        private Activity activity;

        public Builder(Activity activity) {
            this.activity = activity;
            spotlightView = new SpotlightView(activity);
            spotlightView.setSoftwareBtnHeight(getSoftButtonsBarHeight(activity));
        }

        public Builder maskColor(int maskColor) {
            spotlightView.setMaskColor(maskColor);
            return this;
        }

        public Builder introAnimationDuration(long delayMillis) {
            spotlightView.setIntroAnimationDuration(delayMillis);
            return this;
        }

        public Builder enableRevealAnimation(boolean isFadeAnimationEnabled) {
            spotlightView.setRevealAnimationEnabled(isFadeAnimationEnabled);
            return this;
        }

        public Builder target(View view) {
            spotlightView.setTargetView(new ViewTarget(view));
            return this;
        }

        public Builder targetPadding(int padding) {
            spotlightView.setPadding(padding);
            return this;
        }

        public Builder dismissOnTouch(boolean dismissOnTouch) {
            spotlightView.setDismissOnTouch(dismissOnTouch);
            return this;
        }

        public Builder dismissOnBackPress(boolean dismissOnBackPress) {
            spotlightView.setDismissOnBackPress(dismissOnBackPress);
            return this;
        }

        public Builder usageId(String usageId) {
            spotlightView.setUsageId(usageId);
            return this;
        }

        public Builder setTypeface(Typeface typeface) {
            spotlightView.setTypeface(typeface);
            return this;
        }

        public Builder setListener(SpotlightListener spotlightListener) {
            spotlightView.setListener(spotlightListener);
            return this;
        }

        public Builder performClick(boolean isPerformClick) {
            spotlightView.setPerformClick(isPerformClick);
            return this;
        }

        public Builder fadeinTextDuration(long fadinTextDuration) {
            spotlightView.setFadingTextDuration(fadinTextDuration);
            return this;
        }

        public Builder headingTvSize(int headingTvSize) {
            spotlightView.setHeadingTvSize(headingTvSize);
            return this;
        }

        public Builder headingTvSize(int dimenUnit, int headingTvSize) {
            spotlightView.setHeadingTvSize(dimenUnit,headingTvSize);
            return this;
        }

        public Builder headingTvColor(int color) {
            spotlightView.setHeadingTvColor(color);
            return this;
        }

        public Builder headingTvText(CharSequence text) {
            spotlightView.setHeadingTvText(text);
            return this;
        }

        public Builder subHeadingTvSize(int headingTvSize) {
            spotlightView.setSubHeadingTvSize(headingTvSize);
            return this;
        }

        public Builder subHeadingTvSize(int dimenUnit, int headingTvSize) {
            spotlightView.setSubHeadingTvSize(dimenUnit,headingTvSize);
            return this;
        }

        public Builder subHeadingTvColor(int color) {
            spotlightView.setSubHeadingTvColor(color);
            return this;
        }

        public Builder subHeadingTvText(CharSequence text) {
            spotlightView.setSubHeadingTvText(text);
            return this;
        }

        public Builder lineAndArcColor(int color) {
            spotlightView.setLineAndArcColor(color);
            return this;
        }

        public Builder lineAnimDuration(long duration) {
            spotlightView.setLineAnimationDuration(duration);
            return this;
        }

        public Builder showTargetArc(boolean show) {
            spotlightView.setShowTargetArc(show);
            return this;
        }

        public Builder enableDismissAfterShown(boolean enable) {
            if (enable) {
                spotlightView.setEnableDismissAfterShown(enable);
                spotlightView.setDismissOnTouch(false);
            }
            return this;
        }

        public Builder lineStroke(int stroke) {
            spotlightView.setLineStroke(Utils.dpToPx(stroke));
            return this;
        }

        public Builder lineEffect(@Nullable PathEffect pathEffect) {
            spotlightView.setLineEffect(pathEffect);
            return this;
        }

        public Builder setConfiguration(SpotlightConfig configuration) {
            spotlightView.setConfiguration(configuration);
            return this;
        }

        public SpotlightView build() {
            Circle circle = new Circle(
                    spotlightView.targetView,
                    spotlightView.padding);
            spotlightView.setCircleShape(circle);
            if (spotlightView.dismissOnBackPress) {
                spotlightView.enableDismissOnBackPress();
            }
            return spotlightView;
        }

        public SpotlightView show() {
            build().show(activity);
            return spotlightView;
        }

    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (dismissOnBackPress && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            if (event.getAction() == KeyEvent.ACTION_UP) {
                dismiss();
            }
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

    public void logger(String s) {
        Log.d("Spotlight", s);
    }

    private int getViewHeight(){
        if(getWidth() > getHeight()){
            //Landscape
            return getHeight();
        }else{
            //Portrait
            return (getHeight() - softwareBtnHeight);
        }
    }

    private int getViewWidth(){
        if(getWidth() > getHeight()){
            //Landscape
            return (getWidth() - softwareBtnHeight);
        }else{
            //Portrait
            return getWidth();
        }
    }

    private static int getSoftButtonsBarHeight(Activity activity) {
        try{
            // getRealMetrics is only available with API 17 and +
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                DisplayMetrics metrics = new DisplayMetrics();
                activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

                if(metrics.heightPixels > metrics.widthPixels)
                {
                    //Portrait
                    int usableHeight = metrics.heightPixels;
                    activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
                    int realHeight = metrics.heightPixels;
                    if (realHeight > usableHeight)
                        return realHeight - usableHeight;
                    else
                        return 0;
                }else{
                    //Landscape
                    int usableHeight = metrics.widthPixels;
                    activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
                    int realHeight = metrics.widthPixels;
                    if (realHeight > usableHeight)
                        return realHeight - usableHeight;
                    else
                        return 0;
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * This will remove all usage ids from preferences.
     */
    public void resetAllUsageIds(){
        try{
            preferencesManager.resetAll();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * This will remove given usage id from preferences.
     * @param id Spotlight usage id to be removed
     */
    public void resetUsageId(String id){
        try{
            preferencesManager.reset(id);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}


text:
html,
body {
  height: 100%;
  width: 100%;
}
body {
  font-family: 'Merriweather', 'Helvetica Neue', Arial, sans-serif;
}
hr {
  border-color: #0c68c1;
  border-width: 3px;
  max-width: 50px;
}
hr.light {
  border-color: white;
}
a {
  -webkit-transition: all 0.35s;
  -moz-transition: all 0.35s;
  transition: all 0.35s;
  color: #0c68c1;
}
a:hover,
a:focus {
  color: #094e91;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
}
p {
  font-size: 16px;
  line-height: 1.5;
  margin-bottom: 20px;
}
.bg-primary {
  background-color: #0c68c1;
}
.bg-dark {
  background-color: #222222;
  color: white;
}
.text-faded {
  color: rgba(255, 255, 255, 0.7);
}
section {
  padding: 100px 0;
}
aside {
  padding: 50px 0;
}
.no-padding {
  padding: 0;
}
.navbar-default {
  background-color: black;
  border-color: black;
  font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
  -webkit-transition: all 0.35s;
  -moz-transition: all 0.35s;
  transition: all 0.35s;
}
.navbar-default .navbar-header .navbar-brand {
  color: #0c68c1;
  font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
}
.navbar-default .navbar-header .navbar-brand:hover,
.navbar-default .navbar-header .navbar-brand:focus {
  color: #094e91;
}
.navbar-default .navbar-header .navbar-toggle {
  font-weight: 700;
  font-size: 12px;
  color: #eeeeee;
  text-transform: uppercase;
}
.navbar-default .nav > li > a,
.navbar-default .nav > li > a:focus {
  text-transform: uppercase;
  font-weight: 700;
  font-size: 13px;
  color: #eeeeee;
}
.navbar-default .nav > li > a:hover,
.navbar-default .nav > li > a:focus:hover {
  color: #0c68c1;
}
.navbar-default .nav > li.active > a,
.navbar-default .nav > li.active > a:focus {
  color: #0c68c1 !important;
  background-color: transparent;
}
.navbar-default .nav > li.active > a:hover,
.navbar-default .nav > li.active > a:focus:hover {
  background-color: transparent;
}
@media (min-width: 768px) {
  .navbar-default {
    background-color: black;
    border-color: rgba(0, 0, 0, 0.3);
  }
  .navbar-default .navbar-header .navbar-brand {
    color: rgba(255, 255, 255, 0.7);
  }
  .navbar-default .navbar-header .navbar-brand:hover,
  .navbar-default .navbar-header .navbar-brand:focus {
    color: white;
  }
  .navbar-default .nav > li > a,
  .navbar-default .nav > li > a:focus {
    color: rgba(255, 255, 255, 0.7);
  }
  .navbar-default .nav > li > a:hover,
  .navbar-default .nav > li > a:focus:hover {
    color: white;
  }
  .navbar-default.affix {
    background-color: black;
    border-color: rgba(34, 34, 34, 0.05);
  }
  .navbar-default.affix .navbar-header .navbar-brand {
    color: #0c68c1;
    font-size: 14px;
  }
  .navbar-default.affix .navbar-header .navbar-brand:hover,
  .navbar-default.affix .navbar-header .navbar-brand:focus {
    color: #094e91;
  }
  .navbar-default.affix .nav > li > a,
  .navbar-default.affix .nav > li > a:focus {
    color: #eeeeee;
  }
  .navbar-default.affix .nav > li > a:hover,
  .navbar-default.affix .nav > li > a:focus:hover {
    color: #0c68c1;
  }
}
.center {
  text-align: center;
}
header {
  position: relative;
  width: 100%;
  min-height: auto;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  background-size: cover;
  -o-background-size: cover;
  background-position: center;
  background-image: url('../img/header.jpg');
  text-align: center;
  color: white;
}
header .header-content {
  position: relative;
  text-align: center;
  padding: 100px 15px 100px;
  width: 100%;
}
header .header-content .header-content-inner h1 {
  font-weight: 700;
  text-transform: uppercase;
  margin-top: 0;
  margin-bottom: 0;
  font-size: 30px;
}
header .header-content .header-content-inner hr {
  margin: 30px auto;
}
header .header-content .header-content-inner p {
  font-weight: 300;
  color: rgba(255, 255, 255, 0.7);
  font-size: 16px;
  margin-bottom: 50px;
}
@media (min-width: 768px) {
  header {
    min-height: 100%;
  }
  header .header-content {
    position: absolute;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%);
    padding: 0 50px;
  }
  header .header-content .header-content-inner {
    max-width: 1000px;
    margin-left: auto;
    margin-right: auto;
  }
  header .header-content .header-content-inner h1 {
    font-size: 50px;
  }
  header .header-content .header-content-inner p {
    font-size: 18px;
    max-width: 80%;
    margin-left: auto;
    margin-right: auto;
  }
}
#sportlauf {
  position: relative;
  width: 100%;
  min-height: auto;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  background-size: cover;
  -o-background-size: cover;
  background-position: center;
  background-image: url('../img/header_sportlauf.jpg');
  text-align: center;
  color: white;
}
#sportlauf .header-content {
  position: relative;
  text-align: center;
  padding: 100px 15px 100px;
  width: 100%;
}
#sportlauf .header-content .header-content-inner h1 {
  font-weight: 700;
  text-transform: uppercase;
  margin-top: 0;
  margin-bottom: 0;
  font-size: 30px;
}
#sportlauf .header-content .header-content-inner hr {
  margin: 30px auto;
}
#sportlauf .header-content .header-content-inner p {
  font-weight: 300;
  color: rgba(255, 255, 255, 0.7);
  font-size: 16px;
  margin-bottom: 50px;
}
@media (min-width: 768px) {
  #sportlauf {
    min-height: 100%;
  }
  #sportlauf .header-content {
    position: absolute;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%);
    padding: 0 50px;
  }
  #sportlauf .header-content .header-content-inner {
    max-width: 1000px;
    margin-left: auto;
    margin-right: auto;
  }
  #sportlauf .header-content .header-content-inner h1 {
    font-size: 50px;
  }
  #sportlauf .header-content .header-content-inner p {
    font-size: 18px;
    max-width: 80%;
    margin-left: auto;
    margin-right: auto;
  }
}
.section-heading {
  margin-top: 0;
}
.service-box {
  max-width: 400px;
  margin: 50px auto 0;
}
@media (min-width: 992px) {
  .service-box {
    margin: 20px auto 0;
  }
}
.service-box p {
  margin-bottom: 0;
}
.portfolio-box {
  position: relative;
  display: block;
  max-width: 650px;
  margin: 0 auto;
}
.portfolio-box .portfolio-box-caption {
  color: white;
  opacity: 0;
  display: block;
  background: rgba(12, 104, 193, 0.9);
  position: absolute;
  bottom: 0;
  text-align: center;
  width: 100%;
  height: 100%;
  -webkit-transition: all 0.35s;
  -moz-transition: all 0.35s;
  transition: all 0.35s;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content {
  width: 100%;
  text-align: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category,
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
  font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
  padding: 0 15px;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
  text-transform: uppercase;
  font-weight: 600;
  font-size: 14px;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
  font-size: 18px;
}
.portfolio-box:hover .portfolio-box-caption {
  opacity: 1;
}
.portfolio-box:focus {
  outline: none;
}
@media (min-width: 768px) {
  .portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
    font-size: 16px;
  }
  .portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
    font-size: 22px;
  }
}
.call-to-action h2 {
  margin: 0 auto 20px;
}
.text-primary {
  color: #0c68c1;
}
.no-gutter > [class*='col-'] {
  padding-right: 0;
  padding-left: 0;
}
.btn-default {
  color: #222222;
  background-color: white;
  border-color: white;
  -webkit-transition: all 0.35s;
  -moz-transition: all 0.35s;
  transition: all 0.35s;
}
.btn-default:hover,
.btn-default:focus,
.btn-default.focus,
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
  color: #222222;
  background-color: #f2f2f2;
  border-color: #ededed;
}
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
  background-image: none;
}
.btn-default.disabled,
.btn-default[disabled],
fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
  background-color: white;
  border-color: white;
}
.btn-default .badge {
  color: white;
  background-color: #222222;
}
.btn-primary {
  color: white;
  background-color: #0c68c1;
  border-color: #0c68c1;
  -webkit-transition: all 0.35s;
  -moz-transition: all 0.35s;
  transition: all 0.35s;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
  color: white;
  background-color: #0b5ba9;
  border-color: #0a569f;
}
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
  background-image: none;
}
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
  background-color: #0c68c1;
  border-color: #0c68c1;
}
.btn-primary .badge {
  color: #0c68c1;
  background-color: white;
}
.btn {
  font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
  border: none;
  border-radius: 300px;
  font-weight: 700;
  text-transform: uppercase;
}
.btn-xl {
  padding: 15px 30px;
}
::-moz-selection {
  color: white;
  text-shadow: none;
  background: #222222;
}
::selection {
  color: white;
  text-shadow: none;
  background: #222222;
}
img::selection {
  color: white;
  background: transparent;
}
img::-moz-selection {
  color: white;
  background: transparent;
}
body {
  webkit-tap-highlight-color: #222222;
}

redpajama_set_name: RedPajamaGithub


text:
package edu.rpi.tw.string;

import java.util.HashMap;
import java.util.logging.Logger;

/**
 * This is used by 2graffle and COULD be used by xmi for uuid.
 * TODO: find A superclass of ColorManager and UUIDManager and UUIDManager
 *
 * was jv...2-rdf/src/.../.../jv.../rdf/string
 */
public class IDManager {

   enum IDType {UUID, INT64};

   private long    nextID = 0;
   private boolean hitMax = false;

   private HashMap<String,Long> assignments = null;

   private static Logger theLogger = Logger.getLogger(IDManager.class.getName());

// public IDManager() {
//    new IDManager(IDType.INT64);
// }

   /**
    *
    */
   public IDManager() {
      //System.err.println("# created new ID manager.");
      this.assignments = new HashMap<String,Long>();
   }

   /**
    * If the provided label has not been assigned an identifier,
    * assign an identifier that has not been assigned.
    *
    * Requesting the identifier of a label repeatedly returns the same identifier.
    *
    * @param label - A client-side string that uniquely identifies some thing.
    * @return an alternate identifier in the IDType (e.g. UUID, INT64) format that this object
    *         was configured to return.
    */
   public String getIdentifier(String label) {
      String id = "";
      //IDManager.theLogger.finer("  IDM.getIdentifier(" + label + ") --> ");
      //System.err.print("  ("+this.assignments.size()+") " +this.toString()+" getIdentifier(" + label + ") --> ");
      if( this.assignments.containsKey(label) ) {
         // Return the already-assigned identifier
         id = this.assignments.get(label).toString();
         //IDManager.theLogger.finer("  " + label + " already assigned id " + id);
         //System.err.println("already assigned id " + id);
      }else {
         // Assign the next identifier
         this.assignments.put(label,this.getNextID());
         id = Long.toString(this.nextID);
         //IDManager.theLogger.finer(label + " gets id " + id);
         //System.err.println("gets id " + id);
      }
      return id;
   }

   /**
    *
    * @param label
    * @return
    */
   public boolean hasIdentified(String label) {
      //System.err.print("  ("+this.assignments.size()+") " +this.toString()+" hasIdentified(" + label + ") --> "+this.assignments.containsKey(label));
      return this.assignments.containsKey(label);
   }

   /**
    *
    * @return
    */
   private long getNextID()
   {
      // Counter starts at 1, grows to MAX_VALUE, resets to MIN_VALUE and stops at 0
      // 1,2,3, ... 2^64, -2^64, -2^64 - 1, -2^64 - 2, ..., -1, 0, 0, 0, 0, ...
      if (!this.hitMax && this.nextID < Long.MAX_VALUE || this.hitMax && this.nextID < 0)
      {
         this.nextID++;
      }
      else if (!this.hitMax && this.nextID == Long.MAX_VALUE) {
         this.hitMax = true;
         this.nextID = Long.MIN_VALUE;
         IDManager.theLogger.finer("hitMax");
      }
      // Neither of the above conditions is true when identifiers are exhausted
      return this.nextID;
   }

   /**
    *
    * @return
    */
   public boolean hasMoreDistinctAssignments()
   {
      // Counter starts at 1, grows to MAX_VALUE, resets to MIN_VALUE and stops at 0
      return !(this.hitMax && this.nextID == 0);
   }

   /**
    *
    * @param labels
    * @return
    */
   /*public String toString( Set<URI> labels ) {
//    String retVal = "{";
//    for( Object o : labels ) {
//       retVal = retVal + getIdentifier(o.toString()) + ", ";
//    }
//    return retVal+"nil}";

      String retVal ="[";
      Iterator<URI> iter = labels.iterator();
      while( iter.hasNext() ) {
         String val = getIdentifier(iter.next().toString());
         retVal = iter.hasNext() ? retVal + val + ","
                             : retVal + val;
      }
      return retVal + "]";
   }*/

   /**
    *
    * @param args
    */
   public static void main(String args[])
   {
      IDManager idm = new IDManager();
      for (long label = 0; label < Long.MAX_VALUE; label++) {
         System.out.println(Long.toString(label) + " " + idm.getIdentifier(Long.toString(label)));
         //idm.getIdentifier(Long.toString(label));
         System.out.println(Long.toString(label) + " " + idm.getIdentifier(Long.toString(label)));
      }
   }
}


text:
require 'spec_helper'

# Before running this spec again, you need to set environment variable BOLETOSIMPLES_API_TOKEN
RSpec.describe BoletoSimples::SmsDelivery do
  describe 'all', vcr: { cassette_name: 'resources/sns_delivery/all' } do
    subject { described_class.all }

    it { expect(subject.first).to be_nil }
  end
end


text:
<?php

namespace Nov;

class Db
{
    private $dsn;
    private $username;
    private $password;

    public function setDsn($dsn)
    {
        $this->dsn = $dsn;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }

    public function setUsername($username)
    {
        $this->username = $username;
    }

    /** @return \PDO */
    public function getPDO()
    {
        $options = array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION);
        return new \PDO($this->dsn, $this->username, $this->password, $options);
    }
}


text:
class Solution:
    # @param {string} s input string
    # @return {string} the longest palindromic substring
    def longestPalindrome(self, s):
        # Write your code here
        def getlongestpalidrome(self, s, l, r):
        	while l >= 0 and r < len(s) and s[l] == s[r]:
        		l -= 1; r += 1
        	return s[l+1 : r]

        def longestPalindrome(self, s):
        	palindrome = ''
        	for i in xrange(len(s)):
        		len1 = len(self.getlongestpalidrome(s, i , i))
        		if len1 > len(palindrome): palindrome = self.getlongestpalidrome(s, i , i)
        		len2 = len(self.getlongestpalidrome(s, i, i+1))
        		if len2 > len(palindrome): palindrome = self.getlongestpalidrome(s, i, i+1)

        	return palindrome


text:
require 'rails_helper'

RSpec.describe ScoreboardHelper do
  describe '.sort_list' do
    before { create :maneuver }

    let(:asc) { 0 }
    let(:desc) { 1 }
    let(:man_count) do
      Maneuver.count + %i[onboard_judging man_subtotal].count
    end
    let(:score_count) { man_count + %i[circle_check quiz total].count }

    it 'sorts by total score by default' do
      expect(helper.sort_list(nil)).to eq(helper.sort_list(:total_score))
    end

    it 'sorts by total score, descending' do
      expect(helper.sort_list(:total_score)).to eq([[score_count, desc]])
    end

    it 'sorts by maneuver score, descending' do
      expect(helper.sort_list(:maneuver_score)).to eq([[man_count, desc]])
    end

    it 'sorts by participant score, ascending' do
      expect(helper.sort_list(:participant_number)).to eq([[0, asc]])
    end
  end

  describe '.score_data' do
    let(:call) { helper.score_data(nil) }

    it 'is a hash' do
      expect(call).to be_a(Hash)
    end

    it 'has a text and score' do
      expect(call.keys).to contain_exactly(:text, :score)
    end

    context 'without a record' do
      it 'has a very negative text' do
        expect(call.fetch(:text)).to be < -1000
      end

      it 'has a zero score' do
        expect(call.fetch(:score)).to be_zero
      end
    end

    context 'with a record' do
      let(:record) { Struct.new(:score).new(42) }
      let(:call) { helper.score_data(record) }

      it 'has a text of the score of the record' do
        expect(call.fetch(:text)).to be 42
      end

      it 'has a score of the score of the record' do
        expect(call.fetch(:score)).to be 42
      end
    end
  end
end


text:
package com.bladecoder.engineeditor.common;

import com.badlogic.gdx.utils.Align;

public class AlignUtils {

	public static String getAlign(int align) {
		switch (align) {
		case Align.bottomRight:
			return "bottom-right";
		case Align.bottomLeft:
			return "bottom-left";
		case Align.topRight:
			return "top-right";
		case Align.topLeft:
			return "top-left";
		case Align.right:
			return "right";
		case Align.left:
			return "left";
		case Align.bottom:
			return "bottom";
		case Align.top:
			return "top";
		case Align.center:
			return "center";
		}

		return "";
	}

	public static int getAlign(String s) {
		if ("bottom-right".equals(s))
			return Align.bottomRight;
		else if ("bottom-left".equals(s))
			return Align.bottomLeft;
		else if ("top-right".equals(s))
			return Align.topRight;
		else if ("top-left".equals(s))
			return Align.topLeft;
		else if ("right".equals(s))
			return Align.right;
		else if ("left".equals(s))
			return Align.left;
		else if ("bottom".equals(s))
			return Align.bottom;
		else if ("top".equals(s))
			return Align.top;
		else if ("center".equals(s))
			return Align.center;

		return 0;
	}
}


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="vertical_divider">
        <item name="android:layout_width">2dp</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:background">@android:color/darker_gray</item>
    </style>
</resources>


text:
"""
WSGI config for webalyzer project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
"""

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webalyzer.settings')

from django.conf import settings
from django.core.wsgi import get_wsgi_application

from decouple import config
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

# Add media files
if settings.MEDIA_ROOT and settings.MEDIA_URL:
    application.add_files(settings.MEDIA_ROOT, prefix=settings.MEDIA_URL)

# Add NewRelic
newrelic_ini = config('NEW_RELIC_CONFIG_FILE', default='newrelic.ini')
newrelic_license_key = config('NEW_RELIC_LICENSE_KEY', default=None)
if newrelic_ini and newrelic_license_key:
    import newrelic
    newrelic.agent.initialize(newrelic_ini)
    application = newrelic.agent.wsgi_application()(application)


text:
class BlankDetective < Detective
  # Individual detectives must identify their inputs, outputs
  INPUTS = [].freeze  # Input Hash required for Search
  OUTPUTS = [].freeze # Output Hash required to set database values.  Please see
  # database schema for allowed valuses to be set.
  # Setup and major work goes here.  Do not attempt to return anything from this
  # part of the code as it causes crashes.

  def analyze(_evidence, _current)
    {
      # Your return has to go here.  This reformats the hashed return into
      # chief understands.  Remember the output must corrospond to one of the
      # values in the database structure.
      # Typically This would be in the form.

      # blank_status:
      # {
      #  value: 'Met',  # or Unmet
      #  confidence: 3, # or what ever you think it should be.
      #  explanation: "My Text to appear in the evidence field"
      # }
    }
  end
end


text:
<?php
/**
 *
 * Part of the QCubed PHP framework.
 *
 * @license MIT
 *
 */

namespace QCubed\Table;

use QCubed as Q;
use QCubed\Exception\Caller;
use QCubed\Exception\InvalidCast;
use QCubed\ObjectBase;
use QCubed\Project\Application;
use QCubed\TagStyler;
use QCubed\Type;
use QCubed\Control\FormBase;
use QCubed\Project\Control\ControlBase;
use QCubed\Control\TableBase;

/**
 * Class ColumnBase
 *
 * Represents a column for a Table control. Different subclasses (see below) allow accessing and fetching the data
 * for each cells in a variety of ways
 *
 * @property string                 $Name           name of the column
 * @property string                 $CssClass       CSS class of the column. This will be applied to every cell in the column. Use ColStyper
 * 													to set the class for the actual 'col' tag if using col tags.
 * @property string                 $HeaderCssClass CSS class of the column's cells when it's rendered in a table header
 * @property boolean                $HtmlEntities   if true, cell values will be converted using htmlentities()
 * @property boolean                $RenderAsHeader if true, all cells in the column will be rendered with a <<th>> tag instead of <<td>>
 * @property integer                $Id             HTML id attribute to put in the col tag
 * @property integer                $Span           HTML span attribute to put in the col tag
 * @property-read TableBase  $ParentTable    parent table of the column
 * @property-write TableBase $_ParentTable   Parent table of this column
 * @property-write callable $CellParamsCallback A callback to set the html parameters of a generated cell
 * @property boolean                $Visible        Whether the column will be drawn. Defaults to true.
 * @property-read TagStyler		$CellStyler		The tag styler for the cells in the column
 * @property-read TagStyler		$HeaderCellStyler		The tag styler for the header cells in the column
 * @property-read TagStyler		$ColStyler		The tag styler for the col tag in the column
 * @was QAbstractHtmlTableColumn
 * @package QCubed\Table
 */
abstract class ColumnBase extends ObjectBase
{
    /** @var string */
    protected $strName;
    /** @var string */
    protected $strCssClass = null;
    /** @var string */
    protected $strHeaderCssClass = null;
    /** @var boolean */
    protected $blnHtmlEntities = true;
    /** @var boolean */
    protected $blnRenderAsHeader = false;
    /** @var TableBase */
    protected $objParentTable = null;
    /** @var integer */
    protected $intSpan = 1;
    /** @var string optional id for column tag rendering and datatables */
    protected $strId = null;
    /** @var bool Easy way to hide a column without removing the column. */
    protected $blnVisible = true;
    /** @var callable Callback to modify the html attributes of the generated cell. */
    protected $cellParamsCallback = null;
    /** @var TagStyler Styles for each cell. Usually this should be done in css for efficient code generation. */
    protected $objCellStyler;
    /** @var TagStyler Styles for each header cell. Usually this should be done in css for efficient code generation. */
    protected $objHeaderCellStyler;
    /** @var TagStyler Styles for each col. Usually this should be done in css for efficient code generation. */
    protected $objColStyler;

    /**
     * @param string $strName Name of the column
     */
    public function __construct($strName)
    {
        $this->strName = $strName;
    }

    /**
     *
     * Render the header cell including opening and closing tags.
     *
     * This will be called by the data table if ShowHeader is on, and will only
     * be called for the top line item.
     *
     */
    public function renderHeaderCell()
    {
        if (!$this->blnVisible) {
            return '';
        }

        $cellValue = $this->fetchHeaderCellValue();
        if ($this->blnHtmlEntities) {
            $cellValue = Q\QString::htmlEntities($cellValue);
        }
        if ($cellValue == '' && Application::instance()->context()->isBrowser(Q\Context::INTERNET_EXPLORER)) {
            $cellValue = ' ';
        }

        return Q\Html::renderTag('th', $this->getHeaderCellParams(), $cellValue);
    }

    /**
     * Returns the text to print in the header cell, if one is to be drawn. Override if you want
     * something other than the default.
     */
    public function fetchHeaderCellValue()
    {
        return $this->strName;
    }

    /**
     * Returns an array of key/value pairs to insert as parameters in the header cell. Override and add
     * more if you need them.
     * @return array
     */
    public function getHeaderCellParams()
    {
        $aParams['scope'] = 'col';
        if ($this->strHeaderCssClass) {
            $aParams['class'] = $this->strHeaderCssClass;
        }
        if ($this->objHeaderCellStyler) {
            $aParams = $this->objHeaderCellStyler->getHtmlAttributes($aParams);
        }
        return $aParams;
    }

    /**
     * Render a cell.
     * Called by data table for each cell. Override and call with $blnHeader = true if you want
     * this individual cell to render with <<th>> tags instead of <<td>>.
     *
     * @param mixed   $item
     * @param boolean $blnAsHeader
     *
     * @return string
     */
    public function renderCell($item, $blnAsHeader = false)
    {
        if (!$this->blnVisible) {
            return '';
        }

        $cellValue = $this->fetchCellValue($item);
        if ($this->blnHtmlEntities) {
            $cellValue = Q\QString::htmlEntities($cellValue);
        }
        if ($cellValue == '' && Application::instance()->context()->isBrowser(Q\Context::INTERNET_EXPLORER)) {
            $cellValue = ' ';
        }

        if ($blnAsHeader || $this->blnRenderAsHeader) {
            $strTag = 'th';
        } else {
            $strTag = 'td';
        }

        return Q\Html::renderTag($strTag, $this->getCellParams($item), $cellValue);
    }

    /**
     * Return a key/val array of items to insert inside the cell tag.
     * Handles class, style, and id already. Override to add additional items, like an onclick handler.
     *
     * @param mixed $item
     *
     * @return array
     */
    protected function getCellParams($item)
    {
        $aParams = array();

        if ($strClass = $this->getCellClass($item)) {
            $aParams['class'] = $strClass;
        }

        if ($strId = $this->getCellId($item)) {
            $aParams['id'] = $strId;
        }

        if ($this->blnRenderAsHeader) {
            // assume this means it is a row header
            $aParams['scope'] = 'row';
        }

        $strStyle = $this->getCellStyle($item);

        if ($this->objCellStyler) {
            $aStyles = null;
            if ($strStyle) {
                $aStyles = explode(';', $strStyle);
            }
            $aParams = $this->objCellStyler->getHtmlAttributes($aParams, $aStyles);
        } elseif ($strStyle) {
            $aParams['style'] = $strStyle;
        }

        if ($this->cellParamsCallback) {
            $a = call_user_func($this->cellParamsCallback, $item);
            $aParams = array_merge($aParams, $a);
        }

        return $aParams;
    }

    /**
     * Return the class of the cell.
     *
     * @param mixed $item
     *
     * @return string
     */
    protected function getCellClass($item)
    {
        if ($this->strCssClass) {
            return $this->strCssClass;
        }
        return '';
    }

    /**
     * Return the id of the cell.
     *
     * @param mixed $item
     *
     * @return string
     */
    protected function getCellId($item)
    {
        return '';
    }

    /**
     * Return the style string for the cell.
     *
     * @param mixed $item
     *
     * @return string
     */
    protected function getCellStyle($item)
    {
        return '';
    }

    /**
     * Return the raw string that represents the cell value.
     *
     * @param mixed $item
     */
    abstract public function fetchCellValue($item);

    /**
     * Render the column tag.
     * This special tag can control specific features of columns, but is generally optional on a table.
     *
     * @return string
     */
    public function renderColTag()
    {
        return Q\Html::renderTag('col', $this->getColParams(), null, true);
    }

    /**
     * Return a key/value array of parameters to put in the col tag.
     * Override to add parameters.
     */
    protected function getColParams()
    {
        $aParams = array();
        if ($this->intSpan > 1) {
            $aParams['span'] = $this->intSpan;
        }
        if ($this->strId) {
            $aParams['id'] = $this->strId;
        }

        if ($this->objColStyler) {
            $aParams = $this->objColStyler->getHtmlAttributes($aParams);
        }

        return $aParams;
    }

    /**
     * Prepare to serialize references to the form.
     */
    public function sleep()
    {
        $this->cellParamsCallback = ControlBase::sleepHelper($this->cellParamsCallback);
    }

    /**
     * The object has been unserialized, so fix up pointers to embedded objects.
     * @param FormBase $objForm
     */
    public function wakeup(FormBase $objForm)
    {
        $this->cellParamsCallback = ControlBase::wakeupHelper($objForm, $this->cellParamsCallback);
    }

    /**
     * Override to check for post data in your column if needed.
     */
    public function parsePostData()
    {
    }

    /**
     * PHP magic method
     *
     * @param string $strName
     *
     * @return mixed
     * @throws Caller
     */
    public function __get($strName)
    {
        switch ($strName) {
            case 'Name':
                return $this->strName;
            case 'CssClass':
                return $this->strCssClass;
            case 'HeaderCssClass':
                return $this->strHeaderCssClass;
            case 'HtmlEntities':
                return $this->blnHtmlEntities;
            case 'RenderAsHeader':
                return $this->blnRenderAsHeader;
            case 'ParentTable':
                return $this->objParentTable;
            case 'Span':
                return $this->intSpan;
            case 'Id':
                return $this->strId;
            case 'Visible':
                return $this->blnVisible;
            case 'CellStyler':
                if (!$this->objCellStyler) {
                    $this->objCellStyler = new TagStyler();
                }
                return $this->objCellStyler;
            case 'HeaderCellStyler':
                if (!$this->objHeaderCellStyler) {
                    $this->objHeaderCellStyler = new TagStyler();
                }
                return $this->objHeaderCellStyler;
            case 'ColStyler':
                if (!$this->objColStyler) {
                    $this->objColStyler = new TagStyler();
                }
                return $this->objColStyler;

            default:
                try {
                    return parent::__get($strName);
                } catch (Caller $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }
        }
    }

    /**
     * PHP Magic method
     *
     * @param string $strName
     * @param string $mixValue
     *
     * @return mixed|void
     * @throws Caller
     * @throws InvalidCast
     */
    public function __set($strName, $mixValue)
    {
        switch ($strName) {
            case "Name":
                try {
                    $this->strName = Type::cast($mixValue, Type::STRING);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "CssClass":
                try {
                    $this->strCssClass = Type::cast($mixValue, Type::STRING);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "HeaderCssClass":
                try {
                    $this->strHeaderCssClass = Type::cast($mixValue, Type::STRING);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "HtmlEntities":
                try {
                    $this->blnHtmlEntities = Type::cast($mixValue, Type::BOOLEAN);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "RenderAsHeader":
                try {
                    $this->blnRenderAsHeader = Type::cast($mixValue, Type::BOOLEAN);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "Span":
                try {
                    $this->intSpan = Type::cast($mixValue, Type::INTEGER);
                    if ($this->intSpan < 1) {
                        throw new Caller("Span must be 1 or greater.");
                    }
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "Id":
                try {
                    $this->strId = Type::cast($mixValue, Type::STRING);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "Visible":
                try {
                    $this->blnVisible = Type::cast($mixValue, Type::BOOLEAN);
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            case "CellParamsCallback":
                $this->cellParamsCallback = Type::cast($mixValue, Type::CALLABLE_TYPE);
                break;

            case "_ParentTable":
                try {
                    $this->objParentTable = Type::cast($mixValue, 'QCubed\Control\TableBase');
                    break;
                } catch (InvalidCast $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }

            default:
                try {
                    parent::__set($strName, $mixValue);
                    break;
                } catch (Caller $objExc) {
                    $objExc->incrementOffset();
                    throw $objExc;
                }
        }
    }
}


text:
package orst.stratagusai.stratsim.analysis;

import java.util.Collection;
import orst.stratagusai.Unit;
import orst.stratagusai.stratplan.GroupType;
import orst.stratagusai.stratsim.model.GroupSim;

/**
 *
 * @author Brian
 */
public class UnitAnalysis {

    public static boolean isSimulation(Collection<Unit> us) {
        assert !us.isEmpty() : "empty collection of units";
        Boolean sim = null;
        for (Unit u : us) {
            if (sim == null) {
                sim = u instanceof GroupSim;
            } else if (sim) {
                assert u instanceof GroupSim;
            } else {
                assert !(u instanceof GroupSim);
            }
        }
        return sim;
    }

    public static boolean isCombat(Unit u) {
        return isCombat(u.getUnitTypeString());
    }

    public static boolean isCombat(String type) {
        return "unit-footman".equals(type) ||
               "unit-ballista".equals(type) ||
               "unit-knight".equals(type) ||
               "unit-archer".equals(type) ||
               "unit-mage".equals(type) ||
               "unit-paladin".equals(type) ||
               "unit-dwarves".equals(type) ||
               "unit-ranger".equals(type) ||
               "unit-female-hero".equals(type) ||
               "unit-gryphon-rider".equals(type) ||
               "unit-flying-angel".equals(type) ||
               "unit-white-mage".equals(type) ||

               "unit-human-destroyer".equals(type) ||
               "unit-battleship".equals(type) ||
               "unit-human-submarine".equals(type) ||

               // unit-group-combat is created by GameStateAbstractor
               // and ActionProduce.
               GroupType.GROUP_COMBAT.equals(type);
    }

    public static boolean isPeasant(Unit u) {
        return isPeasant(u.getUnitTypeString());
    }

    public static boolean isPeasant(String type) {
        return "unit-peasant".equals(type) ||
               GroupType.GROUP_PEASANT.equals(type);
    }

    /** buildings are units that produce other units. */
    public static boolean isBuilding(Unit u) {
        return isBuilding(u.getUnitTypeString());
    }

    public static boolean isBuilding(String type) {
        return "unit-farm".equals(type) ||
               "unit-human-barracks".equals(type) ||
               "unit-church".equals(type) ||
               "unit-stables".equals(type) ||
               "unit-human-shipyard".equals(type) ||
               "unit-elven-lumber-mill".equals(type) ||
               "unit-human-foundry".equals(type) ||
               "unit-town-hall".equals(type) ||
               "unit-mage-tower".equals(type) ||
               "unit-human-blacksmith".equals(type) ||
               "unit-human-refinery".equals(type) ||
               "unit-human-oil-platform".equals(type) ||

               // unit-group-building is created by GameStateAbstractor and
               // ActionProduce.
               GroupType.GROUP_BUILDING.equals(type);
    }
}


text:
angular.module('citizen-engagement').factory('CameraService', function($q) {

  var service = {
    isSupported: function() {
      return navigator.camera !== undefined;
    },

    getPicture: function() {
      var deferred = $q.defer();
      var options = { // Return the raw base64 PNG data
        destinationType: navigator.camera.DestinationType.DATA_URL,
        correctOrientation: true
      };
      navigator.camera.getPicture(function(result) {
        deferred.resolve(result);
      }, function(err) {
        deferred.reject(err);
      }, options);
      return deferred.promise;
    }
  };
  return service;
});