package yuku.alkitab.base.widget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import yuku.afw.storage.Preferences;
import yuku.alkitab.base.App;
import yuku.alkitab.base.IsiActivity;
import yuku.alkitab.base.storage.Prefkey;
import yuku.alkitab.debug.R;
public class LabeledSplitHandleButton extends SplitHandleButton {
public static final String TAG = LabeledSplitHandleButton.class.getSimpleName();
String label1 = null;
String label2 = null;
Paint labelPaint = new Paint();
Paint bezelPaint = new Paint();
float textSize = 14f;
float label1length;
float label2length;
float rotatelength;
boolean label1pressed = false;
boolean label2pressed = false;
boolean rotatepressed = false;
boolean label1down = false;
boolean label2down = false;
boolean rotatedown = false;
float density;
ButtonPressListener buttonPressListener;
int primaryColor;
int accentColor;
Paint accentColorPaint = new Paint();
Bitmap splitVerticalBitmap;
Bitmap splitHorizontalBitmap;
public enum Button {
start,
end,
rotate,
}
public interface ButtonPressListener {
void onLabelPressed(Button button);
}
public LabeledSplitHandleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
void init() {
density = getResources().getDisplayMetrics().density;
labelPaint.setColor(0xffffffff);
labelPaint.setShadowLayer(2.f * density, 0, 0, 0xff000000);
labelPaint.setTextSize(textSize * density);
if (Build.VERSION.SDK_INT >= 21) {
labelPaint.setTypeface(Typeface.create("sans-serif-medium", 0));
} else {
labelPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
labelPaint.setAntiAlias(true);
bezelPaint.setStyle(Paint.Style.FILL_AND_STROKE);
initializePrimaryColor();
accentColor = ResourcesCompat.getColor(getResources(), R.color.accent, getContext().getTheme());
accentColorPaint.setColor(accentColor);
accentColorPaint.setAntiAlias(true);
rotatelength = getResources().getDimensionPixelSize(R.dimen.split_handle_thickness);
}
public void setButtonPressListener(final ButtonPressListener buttonPressListener) {
this.buttonPressListener = buttonPressListener;
}
public void setLabel1(String label1) {
this.label1 = label1;
invalidate();
}
public void setLabel2(String label2) {
this.label2 = label2;
invalidate();
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
// check if touch is at label1, label2, rotate button, or neither
final int maxLabel1sz = (int) Math.min(140 * density, label1length);
final int maxLabel2sz = (int) Math.min(140 * density, label2length);
final int action = MotionEventCompat.getActionMasked(event);
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
// pos is the x (when orientation is vertical) or y (otherwise)
final float pos;
// length is the width or the height
final int length;
if (orientation == Orientation.vertical) {
pos = event.getX();
length = getWidth();
} else {
pos = event.getY();
length = getHeight();
}
if (action == MotionEvent.ACTION_DOWN) {
label1down = pos < maxLabel1sz;
label2down = pos > length - maxLabel2sz;
rotatedown = pos >= (length - rotatelength) * 0.5f && pos <= (length + rotatelength) * 0.5f;
}
if (action == MotionEvent.ACTION_UP && buttonPressListener != null) {
label1pressed = label1down && pos < maxLabel1sz;
label2pressed = label2down && pos > length - maxLabel2sz;
rotatepressed = rotatedown && pos >= (length - rotatelength) * 0.5f && pos <= (length + rotatelength) * 0.5f;
if (rotatepressed) {
orientation = orientation == Orientation.horizontal ? Orientation.vertical : Orientation.horizontal;
post(() -> buttonPressListener.onLabelPressed(Button.rotate));
} else if (label1pressed) {
post(() -> buttonPressListener.onLabelPressed(Button.start));
} else if (label2pressed) {
post(() -> buttonPressListener.onLabelPressed(Button.end));
}
if (rotatepressed || label1pressed || label2pressed) {
post(() -> {
rotatedown = label1down = label2down = false;
postInvalidate();
});
}
}
if ((action == MotionEvent.ACTION_UP && !label1pressed && !label2pressed && !rotatepressed) || action == MotionEvent.ACTION_CANCEL) {
label1down = label1pressed = false;
label2down = label2pressed = false;
rotatedown = rotatepressed = false;
}
}
final boolean res = super.onTouchEvent(event);
postInvalidate();
return res;
}
@Override protected void onDraw(@NonNull Canvas canvas) {
// DO NOT CALL super.onDraw(canvas);
// always draw unpressed bg color first
canvas.drawColor(primaryColor);
// meaning changes according to orientation
final int length;
final int thickness;
if (orientation == Orientation.vertical) {
length = getWidth();
thickness = getHeight();
} else {
length = getHeight();
thickness = getWidth();
}
final float bezelThickness = 1.5f * density;
// draw bezel only when vertical
if (orientation == Orientation.vertical) {
bezelPaint.setColor(0xff111111);
canvas.drawRect(0, thickness - (int) (bezelThickness + 0.5f), length, thickness, bezelPaint);
}
if (label1down || label2down || rotatedown) {
if (rotatedown) {
final float cl = length * 0.5f;
final float ct = thickness * 0.5f;
final float r = rotatelength * 0.75f;
if (orientation == Orientation.vertical) canvas.drawCircle(cl, ct, r, accentColorPaint);
else canvas.drawCircle(ct, cl, r, accentColorPaint);
} else {
canvas.save();
if (label1down) {
if (orientation == Orientation.vertical) canvas.clipRect(0, 0, label1length, thickness);
else canvas.clipRect(0, 0, thickness, label1length);
} else if (label2down) {
final float fr1 = length - label2length;
if (orientation == Orientation.vertical) canvas.clipRect(fr1, 0, length, thickness);
else canvas.clipRect(0, fr1, thickness, length);
}
canvas.drawColor(accentColor);
canvas.restore();
}
} else {
if (isPressed()) { // not label1 nor label2
canvas.drawColor(accentColor);
}
}
final float pad = 8.f * density;
final float base = thickness * 0.5f + textSize * density * 0.3f;
if (label1 != null) {
if (orientation == Orientation.horizontal) {
canvas.save();
canvas.rotate(-90);
labelPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(label1, -pad, base + bezelThickness * 0.5f, labelPaint);
canvas.restore();
} else {
labelPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(label1, pad, base, labelPaint);
}
label1length = 16 * density + labelPaint.measureText(label1);
}
if (label2 != null) {
if (orientation == Orientation.horizontal) {
canvas.save();
canvas.rotate(-90);
labelPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(label2, -length + pad, base + bezelThickness * 0.5f, labelPaint);
canvas.restore();
} else {
labelPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(label2, length - pad, base, labelPaint);
}
label2length = 16.f * density + labelPaint.measureText(label2);
}
{
final Bitmap splitBitmap = orientation == Orientation.vertical ? getSplitHorizontalBitmap() : getSplitVerticalBitmap();
final float cl = length * 0.5f;
final float ct = thickness * 0.5f;
if (orientation == Orientation.vertical) canvas.drawBitmap(splitBitmap, cl - splitBitmap.getWidth() * 0.5f, ct - splitBitmap.getHeight() * 0.5f, null);
else canvas.drawBitmap(splitBitmap, ct - splitBitmap.getWidth() * 0.5f, cl - splitBitmap.getHeight() * 0.5f, null);
}
}
private Bitmap getSplitVerticalBitmap() {
if (splitVerticalBitmap == null) {
splitVerticalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_split_vertical);
}
return splitVerticalBitmap;
}
private Bitmap getSplitHorizontalBitmap() {
if (splitHorizontalBitmap == null) {
splitHorizontalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_split_horizontal);
}
return splitHorizontalBitmap;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
App.getLbm().registerReceiver(nightModeChangedListener, new IntentFilter(IsiActivity.ACTION_NIGHT_MODE_CHANGED));
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
App.getLbm().unregisterReceiver(nightModeChangedListener);
}
final BroadcastReceiver nightModeChangedListener = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
initializePrimaryColor();
invalidate();
}
};
private void initializePrimaryColor() {
if (Preferences.getBoolean(Prefkey.is_night_mode, false)) {
primaryColor = ResourcesCompat.getColor(getResources(), R.color.primary_night_mode, getContext().getTheme());
} else {
primaryColor = ResourcesCompat.getColor(getResources(), R.color.primary, getContext().getTheme());
}
}
}