package carbon.internal;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.PopupWindow;
import java.util.ArrayList;
import java.util.List;
import carbon.R;
public class DebugOverlay extends PopupWindow {
private boolean drawBounds = true;
private boolean drawGrid = true;
private boolean drawRulers = true;
private Activity context;
private ViewTreeObserver.OnPreDrawListener listener = () -> {
getContentView().postInvalidate();
return true;
};
public DebugOverlay(Activity context) {
super(context);
this.context = context;
}
public void show() {
View anchor = context.getWindow().getDecorView().getRootView();
setContentView(new DebugLayout(context, anchor));
getContentView().setLayoutParams(new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
setBackgroundDrawable(new ColorDrawable(context.getResources().getColor(android.R.color.transparent)));
setTouchable(false);
setFocusable(false);
setOutsideTouchable(false);
setAnimationStyle(0);
super.showAtLocation(anchor, Gravity.START | Gravity.TOP, 0, 0);
update(anchor.getWidth(), anchor.getHeight());
anchor.getViewTreeObserver().addOnPreDrawListener(listener);
}
@Override
public void dismiss() {
View anchor = context.getWindow().getDecorView().getRootView();
anchor.getViewTreeObserver().removeOnPreDrawListener(listener);
super.dismiss();
}
public boolean isDrawBoundsEnabled() {
return drawBounds;
}
public void setDrawBoundsEnabled(boolean drawBounds) {
this.drawBounds = drawBounds;
}
public boolean isDrawGridEnabled() {
return drawGrid;
}
public void setDrawGridEnabled(boolean drawGrid) {
this.drawGrid = drawGrid;
}
public boolean isDrawRulersEnabled() {
return drawRulers;
}
public void setDrawRulersEnabled(boolean drawRulers) {
this.drawRulers = drawRulers;
}
private class DebugLayout extends View {
private final View view;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect rect = new Rect();
Rect rect2 = new Rect();
float step;
private int[] location;
float[] rulers = new float[5];
public DebugLayout(Context context, View view) {
super(context);
this.view = view;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Resources res = context.getResources();
step = res.getDimension(R.dimen.carbon_grid8);
rulers[0] = res.getDimension(R.dimen.carbon_windowPadding);
rulers[1] = res.getDimension(R.dimen.carbon_windowPadding) + res.getDimension(R.dimen.carbon_iconSize);
rulers[2] = res.getDimension(R.dimen.carbon_contentSpace) - res.getDimension(R.dimen.carbon_padding);
rulers[3] = res.getDimension(R.dimen.carbon_contentSpace);
rulers[4] = wm.getDefaultDisplay().getWidth() - res.getDimension(R.dimen.carbon_windowPadding);
}
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
location = new int[2];
getLocationOnScreen(location);
paint.setAlpha(255);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
if (drawGrid) {
paint.setColor(0x1f000000);
for (float x = step; x < getWidth(); x += step) {
canvas.drawLine(x, 0, x, getHeight(), paint);
}
paint.setColor(0x3f000000);
for (float y = step; y < getHeight(); y += step) {
canvas.drawLine(0, y, getWidth(), y, paint);
}
}
if (drawBounds) {
List<View> views = findViews();
for (View v : views)
drawView(canvas, v);
}
if (drawRulers) {
paint.setColor(0x7fff00ff);
for (float ruler : rulers)
canvas.drawLine(ruler, 0, ruler, getHeight(), paint);
paint.setColor(0x3f00ffff);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, rulers[0], getHeight(), paint);
canvas.drawRect(rulers[2], 0, rulers[3], getHeight(), paint);
canvas.drawRect(rulers[4], 0, getWidth(), getHeight(), paint);
}
}
private void drawView(Canvas canvas, View v) {
float vertLine = Math.min(step, v.getWidth() / 3);
float horzLine = Math.min(step, v.getHeight() / 3);
int[] l = new int[2];
v.getLocationOnScreen(l);
v.getDrawingRect(rect);
v.getHitRect(rect2);
rect.offset(l[0] - location[0], l[1] - location[1]);
rect2.offset(l[0] - location[0] - v.getLeft(), l[1] - location[1] - v.getTop());
paint.setStyle(Paint.Style.STROKE);
paint.setColor(0x3f00ff00);
canvas.drawRect(rect, paint);
paint.setColor(0x7f00ff00);
canvas.drawLine(rect.left, rect.top, rect.left + vertLine, rect.top, paint);
canvas.drawLine(rect.left, rect.top, rect.left, rect.top + horzLine, paint);
canvas.drawLine(rect.right, rect.top, rect.right - vertLine, rect.top, paint);
canvas.drawLine(rect.right, rect.top, rect.right, rect.top + horzLine, paint);
canvas.drawLine(rect.left, rect.bottom, rect.left + vertLine, rect.bottom, paint);
canvas.drawLine(rect.left, rect.bottom, rect.left, rect.bottom - horzLine, paint);
canvas.drawLine(rect.right, rect.bottom, rect.right - vertLine, rect.bottom, paint);
canvas.drawLine(rect.right, rect.bottom, rect.right, rect.bottom - horzLine, paint);
if (!rect.equals(rect2)) {
paint.setColor(0x7fff0000);
canvas.drawRect(rect2, paint);
}
}
private List<View> findViews() {
List<View> result = new ArrayList<>();
List<ViewGroup> groups = new ArrayList<>();
if (!(view instanceof ViewGroup)) {
result.add(view);
return result;
}
groups.add((ViewGroup) view);
while (!groups.isEmpty()) {
ViewGroup group = groups.remove(0);
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
result.add(child);
if (child instanceof ViewGroup)
groups.add((ViewGroup) child);
}
}
return result;
}
}
}