1 /*
2  * Copyright (C) 2016 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 
17 package com.android.launcher3.shortcuts;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Rect;
22 import android.graphics.drawable.Drawable;
23 import android.text.TextUtils;
24 import android.util.AttributeSet;
25 
26 import com.android.launcher3.BubbleTextView;
27 import com.android.launcher3.R;
28 import com.android.launcher3.Utilities;
29 
30 /**
31  * A {@link BubbleTextView} that has the shortcut icon on the left and drag handle on the right.
32  */
33 public class DeepShortcutTextView extends BubbleTextView {
34 
35     private boolean mShowLoadingState;
36     private Drawable mLoadingStatePlaceholder;
37     private final Rect mLoadingStateBounds = new Rect();
38 
DeepShortcutTextView(Context context)39     public DeepShortcutTextView(Context context) {
40         this(context, null, 0);
41     }
42 
DeepShortcutTextView(Context context, AttributeSet attrs)43     public DeepShortcutTextView(Context context, AttributeSet attrs) {
44         this(context, attrs, 0);
45     }
46 
DeepShortcutTextView(Context context, AttributeSet attrs, int defStyle)47     public DeepShortcutTextView(Context context, AttributeSet attrs, int defStyle) {
48         super(context, attrs, defStyle);
49         showLoadingState(true);
50     }
51 
52     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)53     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
54         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
55         setLoadingBounds();
56     }
57 
setLoadingBounds()58     private void setLoadingBounds() {
59         if (mLoadingStatePlaceholder == null) {
60             return;
61         }
62         mLoadingStateBounds.set(
63                 0,
64                 0,
65                 getMeasuredWidth() - getPaddingEnd() - getPaddingStart(),
66                 mLoadingStatePlaceholder.getIntrinsicHeight());
67         mLoadingStateBounds.offset(
68                 Utilities.isRtl(getResources()) ? getPaddingEnd() : getPaddingStart(),
69                 (int) ((getMeasuredHeight() - mLoadingStatePlaceholder.getIntrinsicHeight())
70                         / 2.0f)
71         );
72         mLoadingStatePlaceholder.setBounds(mLoadingStateBounds);
73     }
74 
75     @Override
applyCompoundDrawables(Drawable icon)76     protected void applyCompoundDrawables(Drawable icon) {
77         // The icon is drawn in a separate view.
78     }
79 
80     @Override
setText(CharSequence text, BufferType type)81     public void setText(CharSequence text, BufferType type) {
82         super.setText(text, type);
83 
84         if (!TextUtils.isEmpty(text)) {
85             showLoadingState(false);
86         }
87     }
88 
89     @Override
shouldIgnoreTouchDown(float x, float y)90     protected boolean shouldIgnoreTouchDown(float x, float y) {
91         // assume the whole view as clickable
92         return false;
93     }
94 
95     @Override
onDraw(Canvas canvas)96     public void onDraw(Canvas canvas) {
97         if (!mShowLoadingState) {
98             super.onDraw(canvas);
99             return;
100         }
101 
102         mLoadingStatePlaceholder.draw(canvas);
103     }
104 
105     @Override
drawDotIfNecessary(Canvas canvas)106     protected void drawDotIfNecessary(Canvas canvas) {
107         // This view (with the text label to the side of the icon) is not designed for a dot to be
108         // drawn on top of it, so never draw one even if a notification for this shortcut exists.
109     }
110 
showLoadingState(boolean loading)111     private void showLoadingState(boolean loading) {
112         if (loading == mShowLoadingState) {
113             return;
114         }
115 
116         mShowLoadingState = loading;
117 
118         if (loading) {
119             mLoadingStatePlaceholder = getContext().getDrawable(
120                     R.drawable.deep_shortcuts_text_placeholder);
121             setLoadingBounds();
122         } else {
123             mLoadingStatePlaceholder = null;
124         }
125 
126         invalidate();
127     }
128 }
129