com.waz.zclient.pages.main.drawing.DrawingFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.waz.zclient.pages.main.drawing.DrawingFragment.java

Source

/**
 * Wire
 * Copyright (C) 2016 Wire Swiss GmbH
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.waz.zclient.pages.main.drawing;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.media.ExifInterface;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.TextView;
import com.waz.api.BitmapCallback;
import com.waz.api.ImageAsset;
import com.waz.api.ImageAssetFactory;
import com.waz.api.LoadHandle;
import com.waz.api.MemoryImageCache;
import com.waz.utils.wrappers.URI;
import com.waz.zclient.BaseActivity;
import com.waz.zclient.OnBackPressedListener;
import com.waz.zclient.R;
import com.waz.zclient.controllers.accentcolor.AccentColorObserver;
import com.waz.zclient.controllers.drawing.DrawingController;
import com.waz.zclient.controllers.drawing.IDrawingController;
import com.waz.zclient.controllers.globallayout.KeyboardVisibilityObserver;
import com.waz.zclient.controllers.permission.RequestPermissionsObserver;
import com.waz.zclient.pages.BaseFragment;
import com.waz.zclient.pages.main.conversation.AssetIntentsManager;
import com.waz.zclient.tracking.GlobalTrackingController;
import com.waz.zclient.ui.colorpicker.ColorPickerLayout;
import com.waz.zclient.ui.colorpicker.EmojiBottomSheetDialog;
import com.waz.zclient.ui.colorpicker.EmojiSize;
import com.waz.zclient.ui.sketch.DrawingCanvasCallback;
import com.waz.zclient.ui.sketch.DrawingCanvasView;
import com.waz.zclient.ui.text.TypefaceTextView;
import com.waz.zclient.ui.utils.ColorUtils;
import com.waz.zclient.ui.utils.KeyboardUtils;
import com.waz.zclient.ui.utils.MathUtils;
import com.waz.zclient.ui.views.CursorIconButton;
import com.waz.zclient.ui.views.SketchEditText;
import com.waz.zclient.utils.LayoutSpec;
import com.waz.zclient.utils.PermissionUtils;
import com.waz.zclient.utils.TrackingUtils;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.utils.debug.ShakeEventListener;

import java.util.Locale;

public class DrawingFragment extends BaseFragment<DrawingFragment.Container>
        implements OnBackPressedListener, ColorPickerLayout.OnColorSelectedListener, DrawingCanvasCallback,
        ViewTreeObserver.OnScrollChangedListener, AccentColorObserver, AssetIntentsManager.Callback,
        RequestPermissionsObserver, ColorPickerLayout.OnWidthChangedListener, KeyboardVisibilityObserver {

    public static final String TAG = DrawingFragment.class.getName();
    private static final String SAVED_INSTANCE_BITMAP = "SAVED_INSTANCE_BITMAP";
    private static final String ARGUMENT_BACKGROUND_IMAGE = "ARGUMENT_BACKGROUND_IMAGE";
    private static final String ARGUMENT_DRAWING_DESTINATION = "ARGUMENT_DRAWING_DESTINATION";
    private static final String ARGUMENT_DRAWING_METHOD = "ARGUMENT_DRAWING_METHOD";

    private static final String[] SKETCH_FROM_GALLERY_PERMISSION = new String[] {
            Manifest.permission.READ_EXTERNAL_STORAGE };
    private static final int OPEN_SKETCH_FROM_GALLERY = 8864;

    private static final float TEXT_ALPHA_INVISIBLE = 0F;
    private static final float TEXT_ALPHA_MOVE = 0.2F;
    private static final float TEXT_ALPHA_VISIBLE = 1F;
    private static final int SEND_BUTTON_DISABLED_ALPHA = 102;
    private static final int DEFAULT_TEXT_COLOR = Color.WHITE;
    private static final int EDIT_BOX_POS_MARGIN = 10;

    private ShakeEventListener shakeEventListener;
    private SensorManager sensorManager;
    private AssetIntentsManager assetIntentsManager;
    private DrawingCanvasView drawingCanvasView;
    private ColorPickerLayout colorLayout;
    private HorizontalScrollView colorPickerScrollContainer;
    private Toolbar toolbar;

    // TODO uncomment once AN-4649 is fixed
    //private ColorPickerScrollView colorPickerScrollBar;

    private TypefaceTextView drawingViewTip;
    private View drawingTipBackground;

    private CursorIconButton sendDrawingButton;
    private SketchEditText sketchEditTextView;
    private boolean shouldOpenEditText = false;
    private int currentBackgroundColor;
    private TextView actionButtonText;
    private TextView actionButtonEmoji;
    private TextView actionButtonSketch;
    private View galleryButton;
    private int defaultTextColor;

    private ImageAsset backgroundImage;
    private LoadHandle bitmapLoadHandle;

    private DrawingController.DrawingDestination drawingDestination;
    private DrawingController.DrawingMethod drawingMethod;
    private boolean includeBackgroundImage;
    private EmojiSize currentEmojiSize = EmojiSize.SMALL;

    private View.OnTouchListener drawingCanvasViewOnTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                hideTip();
                break;
            }
            return false;
        }
    };
    private Toolbar.OnMenuItemClickListener toolbarOnMenuItemClickListener = new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.close:
                if (getControllerFactory() == null || getControllerFactory().isTornDown()) {
                    return false;
                }
                getControllerFactory().getDrawingController().hideDrawing(drawingDestination, false);
                return true;
            }
            return false;
        }
    };
    private View.OnClickListener toolbarNavigationClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (drawingCanvasView != null) {
                KeyboardUtils.hideKeyboard(getActivity());
                drawingCanvasView.undo();
            }
        }
    };
    private View.OnTouchListener sketchEditTextOnTouchListener = new View.OnTouchListener() {
        private float initialX;
        private float initialY;
        private FrameLayout.LayoutParams params;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (drawingCanvasView.getCurrentMode() == DrawingCanvasView.Mode.TEXT) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    initialX = event.getX();
                    initialY = event.getY();
                    params = (FrameLayout.LayoutParams) sketchEditTextView.getLayoutParams();
                    sketchEditTextView.setAlpha(TEXT_ALPHA_MOVE);
                    break;
                case MotionEvent.ACTION_MOVE:
                    params.leftMargin += (int) (event.getX() - initialX);
                    params.topMargin += (int) (event.getY() - initialY);
                    clampSketchEditBoxPosition(params);
                    sketchEditTextView.setLayoutParams(params);
                    break;
                case MotionEvent.ACTION_UP:
                    closeKeyboard();
                    break;
                }
            }
            return drawingCanvasView.onTouchEvent(event);
        }
    };
    private SketchEditText.SketchEditTextListener sketchEditTextListener = new SketchEditText.SketchEditTextListener() {
        @Override
        public void editTextChanged() {
            sketchEditTextView.setBackground(ColorUtils.getRoundedTextBoxBackground(getContext(),
                    currentBackgroundColor, sketchEditTextView.getMeasuredHeight()));
        }
    };

    public static DrawingFragment newInstance(ImageAsset backgroundAsset,
            DrawingController.DrawingDestination drawingDestination) {
        return DrawingFragment.newInstance(backgroundAsset, drawingDestination,
                IDrawingController.DrawingMethod.DRAW);
    }

    public static DrawingFragment newInstance(ImageAsset backgroundAsset,
            DrawingController.DrawingDestination drawingDestination, DrawingController.DrawingMethod method) {
        DrawingFragment fragment = new DrawingFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable(ARGUMENT_BACKGROUND_IMAGE, backgroundAsset);
        bundle.putString(ARGUMENT_DRAWING_DESTINATION, drawingDestination.toString());
        bundle.putString(ARGUMENT_DRAWING_METHOD, method.toString());
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        backgroundImage = args.getParcelable(ARGUMENT_BACKGROUND_IMAGE);
        drawingDestination = DrawingController.DrawingDestination
                .valueOf(args.getString(ARGUMENT_DRAWING_DESTINATION));
        drawingMethod = DrawingController.DrawingMethod.valueOf(args.getString(ARGUMENT_DRAWING_METHOD));
        sensorManager = (SensorManager) getActivity().getSystemService(Activity.SENSOR_SERVICE);
        defaultTextColor = ContextCompat.getColor(getContext(), R.color.text__primary_light);
        assetIntentsManager = new AssetIntentsManager(getActivity(), this, savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_drawing, container, false);
        drawingCanvasView = ViewUtils.getView(rootView, R.id.dcv__canvas);
        drawingCanvasView.setDrawingCanvasCallback(this);
        drawingCanvasView.setDrawingColor(getControllerFactory().getAccentColorController().getColor());
        drawingCanvasView.setOnTouchListener(drawingCanvasViewOnTouchListener);

        colorPickerScrollContainer = ViewUtils.getView(rootView, R.id.hsv_color_picker_scroll_view);

        colorLayout = ViewUtils.getView(rootView, R.id.cpdl__color_layout);
        colorLayout.setOnColorSelectedListener(this);
        int[] colors = getResources().getIntArray(R.array.draw_color);
        colorLayout.setAccentColors(colors, getControllerFactory().getAccentColorController().getColor());
        colorLayout.getViewTreeObserver().addOnScrollChangedListener(this);

        // TODO uncomment once AN-4649 is fixed
        //        colorPickerScrollBar = ViewUtils.getView(rootView, R.id.cpsb__color_picker_scrollbar);
        //        colorPickerScrollBar.setScrollBarColor(getControllerFactory().getAccentColorController().getColor());

        TypefaceTextView conversationTitle = ViewUtils.getView(rootView, R.id.tv__drawing_toolbar__title);
        conversationTitle.setText(getStoreFactory().getConversationStore().getCurrentConversation().getName()
                .toUpperCase(Locale.getDefault()));
        toolbar = ViewUtils.getView(rootView, R.id.t_drawing_toolbar);
        toolbar.inflateMenu(R.menu.toolbar_sketch);
        toolbar.setOnMenuItemClickListener(toolbarOnMenuItemClickListener);
        toolbar.setNavigationOnClickListener(toolbarNavigationClickListener);
        toolbar.setNavigationIcon(R.drawable.toolbar_action_undo_disabled);

        actionButtonText = ViewUtils.getView(rootView, R.id.gtv__drawing_button__text);
        actionButtonText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onTextClick();
            }
        });
        actionButtonEmoji = ViewUtils.getView(rootView, R.id.gtv__drawing_button__emoji);
        actionButtonEmoji.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onEmojiClick();
            }
        });
        actionButtonSketch = ViewUtils.getView(rootView, R.id.gtv__drawing_button__sketch);
        actionButtonSketch.setTextColor(getControllerFactory().getAccentColorController().getColor());
        actionButtonSketch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onSketchClick();
            }
        });

        galleryButton = ViewUtils.getView(rootView, R.id.gtv__drawing__gallery_button);
        galleryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (PermissionUtils.hasSelfPermissions(getContext(), SKETCH_FROM_GALLERY_PERMISSION)) {
                    sketchEditTextView.destroyDrawingCache();
                    assetIntentsManager.openGalleryForSketch();
                } else {
                    ActivityCompat.requestPermissions(getActivity(), SKETCH_FROM_GALLERY_PERMISSION,
                            OPEN_SKETCH_FROM_GALLERY);
                }
            }
        });

        drawingTipBackground = ViewUtils.getView(rootView, R.id.v__tip_background);
        drawingViewTip = ViewUtils.getView(rootView, R.id.ttv__drawing__view__tip);
        drawingTipBackground.setVisibility(View.INVISIBLE);

        sendDrawingButton = ViewUtils.getView(rootView, R.id.tv__send_button);
        sendDrawingButton.setOnClickListener(sketchButtonsOnClickListener);
        sendDrawingButton.setClickable(false);

        sketchEditTextView = ViewUtils.getView(rootView, R.id.et__sketch_text);
        sketchEditTextView.setAlpha(TEXT_ALPHA_INVISIBLE);
        sketchEditTextView.setVisibility(View.INVISIBLE);
        sketchEditTextView.setCustomHint(getString(R.string.drawing__text_hint));
        currentBackgroundColor = getControllerFactory().getAccentColorController().getColor();
        sketchEditTextView.setBackground(ColorUtils.getTransparentDrawable());
        sketchEditTextView.setHintFontId(R.string.wire__typeface__medium);
        sketchEditTextView.setTextFontId(R.string.wire__typeface__regular);
        sketchEditTextView.setSketchScale(1.0f);
        sketchEditTextView.setOnTouchListener(sketchEditTextOnTouchListener);

        if (savedInstanceState != null) {
            Bitmap savedBitmap = savedInstanceState.getParcelable(SAVED_INSTANCE_BITMAP);
            if (savedBitmap != null) {
                // Use saved background image if exists
                drawingCanvasView.setBackgroundBitmap(savedBitmap);
            } else {
                setBackgroundBitmap(true);
            }
        } else {
            setBackgroundBitmap(true);
        }

        return rootView;
    }

    private void hideTip() {
        if (drawingViewTip.getVisibility() == View.GONE) {
            return;
        }
        drawingViewTip.setVisibility(View.GONE);
        drawingTipBackground.setVisibility(View.GONE);
        drawingCanvasView.setOnTouchListener(null);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(SAVED_INSTANCE_BITMAP, getBitmapDrawing());
        assetIntentsManager.onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

    public void setBackgroundBitmap(boolean showHint) {
        if (getActivity() == null || backgroundImage == null) {
            return;
        }

        if (showHint) {
            drawingViewTip.setText(getResources().getString(R.string.drawing__tip__picture__message));
            drawingTipBackground.setVisibility(View.VISIBLE);
        } else {
            hideTip();
        }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            //noinspection deprecation
            drawingViewTip.setTextColor(getResources().getColor(R.color.drawing__tip__font__color_image));
        } else {
            drawingViewTip.setTextColor(
                    getResources().getColor(R.color.drawing__tip__font__color_image, getContext().getTheme()));
        }
        cancelLoadHandle();
        bitmapLoadHandle = backgroundImage.getSingleBitmap(
                ViewUtils.getOrientationDependentDisplayWidth(getActivity()), new BitmapCallback() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap) {
                        if (getActivity() == null || drawingCanvasView == null) {
                            return;
                        }
                        includeBackgroundImage = true;
                        drawingCanvasView.setBackgroundBitmap(bitmap);
                        cancelLoadHandle();

                        if (drawingMethod == IDrawingController.DrawingMethod.EMOJI) {
                            onEmojiClick();
                        } else if (drawingMethod == IDrawingController.DrawingMethod.TEXT) {
                            onTextClick();
                        }
                    }

                    @Override
                    public void onBitmapLoadingFailed(BitmapLoadingFailed reason) {
                        cancelLoadHandle();
                    }
                });
    }

    @Override
    public void onStart() {
        super.onStart();
        colorLayout.setOnWidthChangedListener(this);
        shakeEventListener = new ShakeEventListener();
        shakeEventListener.setOnShakeListener(new ShakeEventListener.OnShakeListener() {
            @Override
            public void onShake() {
                if (includeBackgroundImage) {
                    drawingCanvasView.removeBackgroundBitmap();
                    includeBackgroundImage = false;
                } else {
                    drawingCanvasView.drawBackgroundBitmap();
                    includeBackgroundImage = true;
                }
            }
        });
        sensorManager.registerListener(shakeEventListener,
                sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
        getControllerFactory().getGlobalLayoutController().addKeyboardVisibilityObserver(this);
        getControllerFactory().getAccentColorController().addAccentColorObserver(this);
        getControllerFactory().getRequestPermissionsController().addObserver(this);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (LayoutSpec.isTablet(getActivity())) {
            ViewUtils.lockScreenOrientation(Configuration.ORIENTATION_PORTRAIT, getActivity());
        }
    }

    @Override
    public void onStop() {
        getControllerFactory().getAccentColorController().removeAccentColorObserver(this);
        getControllerFactory().getGlobalLayoutController().removeKeyboardVisibilityObserver(this);
        getControllerFactory().getRequestPermissionsController().removeObserver(this);
        sensorManager.unregisterListener(shakeEventListener);
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        if (drawingCanvasView != null) {
            drawingCanvasView.onDestroy();
            drawingCanvasView = null;
        }
        colorLayout = null;
        sendDrawingButton = null;
        cancelLoadHandle();
        super.onDestroyView();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        assetIntentsManager.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onDataReceived(AssetIntentsManager.IntentType type, URI uri) {
        switch (type) {
        case SKETCH_FROM_GALLERY:
            drawingMethod = IDrawingController.DrawingMethod.DRAW;
            sketchEditTextView.setText("");
            sketchEditTextView.setVisibility(View.GONE);
            drawingCanvasView.reset();
            drawingCanvasView.removeBackgroundBitmap();
            backgroundImage = ImageAssetFactory.getImageAsset(uri);
            setBackgroundBitmap(false);
            onSketchClick();
            break;
        }
    }

    @Override
    public void onCanceled(AssetIntentsManager.IntentType type) {

    }

    @Override
    public void onFailed(AssetIntentsManager.IntentType type) {

    }

    @Override
    public void openIntent(Intent intent, AssetIntentsManager.IntentType intentType) {
        startActivityForResult(intent, intentType.requestCode);
        getActivity().overridePendingTransition(R.anim.camera_in, R.anim.camera_out);
    }

    @Override
    public void onPermissionFailed(AssetIntentsManager.IntentType type) {

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, int[] grantResults) {
        if (assetIntentsManager.onRequestPermissionsResult(requestCode, grantResults)) {
            return;
        }

        switch (requestCode) {
        case OPEN_SKETCH_FROM_GALLERY:
            if (PermissionUtils.verifyPermissions(grantResults)) {
                assetIntentsManager.openGalleryForSketch();
            }
        }
    }

    public void cancelLoadHandle() {
        if (bitmapLoadHandle != null) {
            bitmapLoadHandle.cancel();
            bitmapLoadHandle = null;
        }
    }

    private Bitmap getBitmapDrawing() {
        return drawingCanvasView.getBitmap();
    }

    @Override
    public boolean onBackPressed() {
        if (isShowingKeyboard()) {
            closeKeyboard();
            return true;
        }
        if (drawingCanvasView != null && drawingCanvasView.undo()) {
            return true;
        }
        getControllerFactory().getDrawingController().hideDrawing(drawingDestination, false);
        return true;
    }

    @Override
    public void onScrollWidthChanged(int width) {
        // TODO uncomment once AN-4649 is fixed
        //colorPickerScrollBar.setScrollBarSize(width);
    }

    private View.OnClickListener sketchButtonsOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (drawingCanvasView == null) {
                return;
            }
            switch (v.getId()) {
            case R.id.tv__send_button:
                if (!drawingCanvasView.isEmpty()) {
                    getStoreFactory().getConversationStore().sendMessage(getFinalSketchImage());
                    TrackingUtils.onSentSketchMessage(
                            ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class),
                            getStoreFactory().getConversationStore().getCurrentConversation(), drawingDestination);

                    getControllerFactory().getDrawingController().hideDrawing(drawingDestination, true);
                }
                break;
            default:
                //nothing
                break;
            }
        }
    };

    private ImageAsset getFinalSketchImage() {
        Bitmap finalBitmap = getBitmapDrawing();
        try {
            Rect bitmapTrim = drawingCanvasView.getImageTrimValues();
            MemoryImageCache.reserveImageMemory(bitmapTrim.width(), bitmapTrim.height());
            finalBitmap = Bitmap.createBitmap(finalBitmap, bitmapTrim.left, bitmapTrim.top, bitmapTrim.width(),
                    bitmapTrim.height());
        } catch (Throwable t) {
            // ignore
        }
        return ImageAssetFactory.getImageAsset(finalBitmap, ExifInterface.ORIENTATION_NORMAL);
    }

    @Override
    public void onScrollChanged() {
        // TODO uncomment once AN-4649 is fixed
        //if (colorPickerScrollBar == null || colorLayout == null) {
        //    return;
        //}
        //colorPickerScrollBar.setLeftX(colorPickerScrollContainer.getScrollX());
    }

    @Override
    public void onAccentColorHasChanged(Object sender, int color) {
        // TODO uncomment once AN-4649 is fixed
        //colorPickerScrollBar.setBackgroundColor(color);
        if (drawingCanvasView.isEmpty()) {
            int accentColorWithAlpha = ColorUtils.injectAlpha(SEND_BUTTON_DISABLED_ALPHA,
                    getControllerFactory().getAccentColorController().getColor());
            sendDrawingButton.setSolidBackgroundColor(accentColorWithAlpha);
        } else {
            sendDrawingButton.setSolidBackgroundColor(getControllerFactory().getAccentColorController().getColor());
        }
    }

    @Override
    public void onColorSelected(int color, int strokeSize) {
        if (drawingCanvasView == null) {
            return;
        }
        drawingCanvasView.setDrawingColor(color);
        drawingCanvasView.setStrokeSize(strokeSize);
        currentBackgroundColor = color;
        sketchEditTextView.setBackground(
                ColorUtils.getRoundedTextBoxBackground(getContext(), color, sketchEditTextView.getHeight()));
        if (MathUtils.floatEqual(sketchEditTextView.getAlpha(), TEXT_ALPHA_INVISIBLE)) {
            drawSketchEditText();
        }
    }

    public void onEmojiClick() {
        final EmojiBottomSheetDialog dialog = new EmojiBottomSheetDialog(getContext(), currentEmojiSize,
                new EmojiBottomSheetDialog.EmojiDialogListener() {
                    @Override
                    public void onEmojiSelected(String emoji, EmojiSize emojiSize) {
                        actionButtonEmoji
                                .setTextColor(getControllerFactory().getAccentColorController().getColor());
                        actionButtonSketch.setTextColor(defaultTextColor);
                        actionButtonText.setTextColor(defaultTextColor);
                        drawingCanvasView.setEmoji(emoji, emojiSize.getEmojiSize(getContext()));
                        currentEmojiSize = emojiSize;
                        getControllerFactory().getUserPreferencesController().addRecentEmoji(emoji);
                    }
                }, getControllerFactory().getUserPreferencesController().getRecentEmojis(),
                getControllerFactory().getUserPreferencesController().getUnsupportedEmojis());
        dialog.show();
    }

    private void closeKeyboard() {
        drawSketchEditText();
        KeyboardUtils.hideKeyboard(getActivity());
    }

    private void showKeyboard() {
        drawingCanvasView.hideText();
        sketchEditTextView.setCursorVisible(true);
        sketchEditTextView.requestFocus();
        KeyboardUtils.showKeyboard(getActivity());
    }

    private boolean isShowingKeyboard() {
        return sketchEditTextView.getVisibility() == View.VISIBLE
                && Float.compare(sketchEditTextView.getAlpha(), TEXT_ALPHA_VISIBLE) == 0
                && KeyboardUtils.isKeyboardVisible(getContext());
    }

    private void onSketchClick() {
        drawingCanvasView.setCurrentMode(DrawingCanvasView.Mode.SKETCH);
        actionButtonText.setTextColor(defaultTextColor);
        actionButtonEmoji.setTextColor(defaultTextColor);
        actionButtonSketch.setTextColor(getControllerFactory().getAccentColorController().getColor());
    }

    private void onTextClick() {
        actionButtonText.setTextColor(getControllerFactory().getAccentColorController().getColor());
        actionButtonEmoji.setTextColor(defaultTextColor);
        actionButtonSketch.setTextColor(defaultTextColor);
        drawingCanvasView.setCurrentMode(DrawingCanvasView.Mode.TEXT);
        if (isShowingKeyboard()) {
            closeKeyboard();
        } else {
            if (sketchEditTextView.getVisibility() != View.VISIBLE) {
                shouldOpenEditText = true;
                sketchEditTextView.setAlpha(TEXT_ALPHA_INVISIBLE);
                sketchEditTextView.setBackground(ColorUtils.getTransparentDrawable());
            }
            sketchEditTextView.setVisibility(View.VISIBLE);
            showKeyboard();
            hideTip();
        }
    }

    @Override
    public void drawingAdded() {
        if (isShowingKeyboard()) {
            closeKeyboard();
        }
        toolbar.setNavigationIcon(R.drawable.toolbar_action_undo);
        sendDrawingButton.setSolidBackgroundColor(getControllerFactory().getAccentColorController().getColor());
        sendDrawingButton.setClickable(true);
    }

    @Override
    public void drawingCleared() {
        toolbar.setNavigationIcon(R.drawable.toolbar_action_undo_disabled);
        int colorWithAlpha = ColorUtils.injectAlpha(SEND_BUTTON_DISABLED_ALPHA,
                getControllerFactory().getAccentColorController().getColor());
        sendDrawingButton.setSolidBackgroundColor(colorWithAlpha);
        sendDrawingButton.setClickable(false);
    }

    @Override
    public void reserveBitmapMemory(int width, int height) {
        MemoryImageCache.reserveImageMemory(width, height);
    }

    @Override
    public void onScaleChanged(float scale) {
        sketchEditTextView.setSketchScale(scale);
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) sketchEditTextView.getLayoutParams();
        clampSketchEditBoxPosition(params);
        sketchEditTextView.setLayoutParams(params);
    }

    @Override
    public void onScaleStart() {
        drawingCanvasView.hideText();
        sketchEditTextView.setAlpha(TEXT_ALPHA_VISIBLE);
    }

    @Override
    public void onScaleEnd() {
        closeKeyboard();
    }

    @Override
    public void onTextChanged(String text, int x, int y, float scale) {
        ViewUtils.setMarginLeft(sketchEditTextView, x);
        ViewUtils.setMarginTop(sketchEditTextView, y);
        sketchEditTextView.setSketchScale(scale);
        sketchEditTextView.setText(text);
        sketchEditTextView.setSelection(text.length());
    }

    @Override
    public void onTextRemoved() {
        sketchEditTextView.setText("");
        sketchEditTextView.removeListener(sketchEditTextListener);
        sketchEditTextView.setVisibility(View.INVISIBLE);
    }

    @Override
    public void onKeyboardVisibilityChanged(boolean keyboardIsVisible, int keyboardHeight, View currentFocus) {
        if (!keyboardIsVisible) {
            closeKeyboard();
        }
        if (shouldOpenEditText) {
            shouldOpenEditText = false;
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) sketchEditTextView.getLayoutParams();
            params.leftMargin = (((ViewGroup) sketchEditTextView.getParent()).getMeasuredWidth()
                    - sketchEditTextView.getMeasuredWidth()) / 2;
            params.topMargin = ((ViewGroup) sketchEditTextView.getParent()).getMeasuredHeight() - keyboardHeight
                    - sketchEditTextView.getMeasuredHeight();
            sketchEditTextView.setLayoutParams(params);

            //Posted so that the user doesn't see the previous location
            getView().post(new Runnable() {
                @Override
                public void run() {
                    sketchEditTextView.setBackground(ColorUtils.getRoundedTextBoxBackground(getContext(),
                            currentBackgroundColor, sketchEditTextView.getMeasuredHeight()));
                    sketchEditTextView.setAlpha(TEXT_ALPHA_VISIBLE);
                    sketchEditTextView.addListener(sketchEditTextListener);
                }
            });
        } else {
            sketchEditTextView.setAlpha(TEXT_ALPHA_VISIBLE);
        }

    }

    private void drawSketchEditText() {
        if (sketchEditTextView.getVisibility() == View.VISIBLE) {
            sketchEditTextView.setAlpha(TEXT_ALPHA_VISIBLE);
            sketchEditTextView.setCursorVisible(false);
            //This has to be on a post otherwise the setAlpha and setCursor won't be noticeable in the drawing cache
            getView().post(new Runnable() {
                @Override
                public void run() {
                    sketchEditTextView.setDrawingCacheEnabled(true);
                    Bitmap bitmapDrawingCache = sketchEditTextView.getDrawingCache();
                    if (bitmapDrawingCache != null) {
                        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) sketchEditTextView
                                .getLayoutParams();
                        drawingCanvasView.showText();
                        drawingCanvasView.drawTextBitmap(
                                bitmapDrawingCache.copy(bitmapDrawingCache.getConfig(), true), params.leftMargin,
                                params.topMargin, sketchEditTextView.getText().toString(),
                                sketchEditTextView.getSketchScale());
                    } else {
                        drawingCanvasView.drawTextBitmap(null, 0, 0, "", 1.0f);
                    }
                    sketchEditTextView.setDrawingCacheEnabled(false);
                    sketchEditTextView.setAlpha(TEXT_ALPHA_INVISIBLE);
                }
            });
        }
    }

    private void clampSketchEditBoxPosition(FrameLayout.LayoutParams params) {
        int sketchWidth = (((ViewGroup) sketchEditTextView.getParent()).getMeasuredWidth());
        int sketchHeight = (((ViewGroup) sketchEditTextView.getParent()).getMeasuredHeight());
        int textWidth = sketchEditTextView.getMeasuredWidth();
        int textHeight = sketchEditTextView.getMeasuredHeight();

        params.leftMargin = Math.min(params.leftMargin, sketchWidth - textWidth / 2);
        params.topMargin = Math.min(params.topMargin, sketchHeight - textHeight / 2);
        params.leftMargin = Math.max(params.leftMargin, -textWidth / 2);
        params.topMargin = Math.max(params.topMargin, -textHeight / 2);
    }

    public interface Container {
    }
}