1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.recents.views;
18
19import android.content.Context;
20import android.graphics.Canvas;
21import android.graphics.Paint;
22import android.graphics.Rect;
23import android.util.AttributeSet;
24import android.util.Pair;
25import android.view.View;
26import android.widget.FrameLayout;
27import android.widget.SeekBar;
28import com.android.systemui.R;
29import com.android.systemui.recents.RecentsConfiguration;
30
31import java.util.ArrayList;
32
33/**
34 * A full screen overlay layer that allows us to draw views from throughout the system on the top
35 * most layer.
36 */
37public class DebugOverlayView extends FrameLayout implements SeekBar.OnSeekBarChangeListener {
38
39    public interface DebugOverlayViewCallbacks {
40        public void onPrimarySeekBarChanged(float progress);
41        public void onSecondarySeekBarChanged(float progress);
42    }
43
44    final static int sCornerRectSize = 50;
45
46    RecentsConfiguration mConfig;
47    DebugOverlayViewCallbacks mCb;
48
49    ArrayList<Pair<Rect, Integer>> mRects = new ArrayList<Pair<Rect, Integer>>();
50    String mText;
51    Paint mDebugOutline = new Paint();
52    Paint mTmpPaint = new Paint();
53    Rect mTmpRect = new Rect();
54    boolean mEnabled = true;
55
56    SeekBar mPrimarySeekBar;
57    SeekBar mSecondarySeekBar;
58
59    public DebugOverlayView(Context context) {
60        this(context, null);
61    }
62
63    public DebugOverlayView(Context context, AttributeSet attrs) {
64        this(context, attrs, 0);
65    }
66
67    public DebugOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
68        this(context, attrs, defStyleAttr, 0);
69    }
70
71    public DebugOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
72        super(context, attrs, defStyleAttr, defStyleRes);
73        mConfig = RecentsConfiguration.getInstance();
74        mDebugOutline.setColor(0xFFff0000);
75        mDebugOutline.setStyle(Paint.Style.STROKE);
76        mDebugOutline.setStrokeWidth(8f);
77        setWillNotDraw(false);
78    }
79
80    public void setCallbacks(DebugOverlayViewCallbacks cb) {
81        mCb = cb;
82    }
83
84    @Override
85    protected void onFinishInflate() {
86        mPrimarySeekBar = (SeekBar) findViewById(R.id.debug_seek_bar_1);
87        mPrimarySeekBar.setOnSeekBarChangeListener(this);
88        mSecondarySeekBar = (SeekBar) findViewById(R.id.debug_seek_bar_2);
89        mSecondarySeekBar.setOnSeekBarChangeListener(this);
90    }
91
92    /** Enables the debug overlay drawing. */
93    public void enable() {
94        mEnabled = true;
95        setVisibility(View.VISIBLE);
96    }
97
98    /** Disables the debug overlay drawing. */
99    public void disable() {
100        mEnabled = false;
101        setVisibility(View.GONE);
102    }
103
104    /** Clears all debug rects. */
105    public void clear() {
106        mRects.clear();
107    }
108
109    /** Adds a rect to be drawn. */
110    void addRect(Rect r, int color) {
111        mRects.add(new Pair<Rect, Integer>(r, color));
112        invalidate();
113    }
114
115    /** Adds a view's global rect to be drawn. */
116    void addViewRect(View v, int color) {
117        Rect vr = new Rect();
118        v.getGlobalVisibleRect(vr);
119        mRects.add(new Pair<Rect, Integer>(vr, color));
120        invalidate();
121    }
122
123    /** Adds a rect, relative to a given view to be drawn. */
124    void addRectRelativeToView(View v, Rect r, int color) {
125        Rect vr = new Rect();
126        v.getGlobalVisibleRect(vr);
127        r.offsetTo(vr.left, vr.top);
128        mRects.add(new Pair<Rect, Integer>(r, color));
129        invalidate();
130    }
131
132    /** Sets the debug text at the bottom of the screen. */
133    void setText(String message) {
134        mText = message;
135        invalidate();
136    }
137
138    @Override
139    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
140        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
141        addRect(new Rect(0, 0, sCornerRectSize, sCornerRectSize), 0xFFff0000);
142        addRect(new Rect(getMeasuredWidth() - sCornerRectSize, getMeasuredHeight() - sCornerRectSize,
143                getMeasuredWidth(), getMeasuredHeight()), 0xFFff0000);
144    }
145
146    @Override
147    protected void onDraw(Canvas canvas) {
148        if (mEnabled) {
149            // Draw the outline
150            canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugOutline);
151
152            // Draw the rects
153            int numRects = mRects.size();
154            for (int i = 0; i < numRects; i++) {
155                Pair<Rect, Integer> r = mRects.get(i);
156                mTmpPaint.setColor(r.second);
157                canvas.drawRect(r.first, mTmpPaint);
158            }
159
160            // Draw the text
161            if (mText != null && mText.length() > 0) {
162                mTmpPaint.setColor(0xFFff0000);
163                mTmpPaint.setTextSize(60);
164                mTmpPaint.getTextBounds(mText, 0, 1, mTmpRect);
165                canvas.drawText(mText, 10f, getMeasuredHeight() - mTmpRect.height() - mConfig.systemInsets.bottom, mTmpPaint);
166            }
167        }
168    }
169
170    /**** SeekBar.OnSeekBarChangeListener Implementation ****/
171
172    @Override
173    public void onStopTrackingTouch(SeekBar seekBar) {
174        // Do nothing
175    }
176
177    @Override
178    public void onStartTrackingTouch(SeekBar seekBar) {
179        // Do nothing
180    }
181
182    @Override
183    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
184        if (seekBar == mPrimarySeekBar) {
185            mCb.onPrimarySeekBarChanged((float) progress / mPrimarySeekBar.getMax());
186        } else if (seekBar == mSecondarySeekBar) {
187            mCb.onSecondarySeekBarChanged((float) progress / mSecondarySeekBar.getMax());
188        }
189    }
190}
191