1 /*
2  * Copyright (C) 2013 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.gallery3d.filtershow.state;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.graphics.*;
22 import android.view.MotionEvent;
23 import android.view.View;
24 import android.widget.LinearLayout;
25 import com.android.gallery3d.R;
26 import com.android.gallery3d.filtershow.FilterShowActivity;
27 import com.android.gallery3d.filtershow.category.SwipableView;
28 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
29 import com.android.gallery3d.filtershow.imageshow.PrimaryImage;
30 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
31 
32 public class StateView extends View implements SwipableView {
33 
34     private static final String LOGTAG = "StateView";
35     private Path mPath = new Path();
36     private Paint mPaint = new Paint();
37 
38     public static int DEFAULT = 0;
39     public static int BEGIN = 1;
40     public static int END = 2;
41 
42     public static int UP = 1;
43     public static int DOWN = 2;
44     public static int LEFT = 3;
45     public static int RIGHT = 4;
46 
47     private int mType = DEFAULT;
48     private float mAlpha = 1.0f;
49     private String mText = "Default";
50     private float mTextSize = 32;
51     private static int sMargin = 16;
52     private static int sArrowHeight = 16;
53     private static int sArrowWidth = 8;
54     private float mStartTouchX = 0;
55     private float mStartTouchY = 0;
56     private float mDeleteSlope = 20;
57 
58     private int mOrientation = LinearLayout.VERTICAL;
59     private int mDirection = DOWN;
60     private boolean mDuplicateButton;
61     private State mState;
62 
63     private int mEndsBackgroundColor;
64     private int mEndsTextColor;
65     private int mBackgroundColor;
66     private int mTextColor;
67     private int mSelectedBackgroundColor;
68     private int mSelectedTextColor;
69     private Rect mTextBounds = new Rect();
70 
StateView(Context context)71     public StateView(Context context) {
72         this(context, DEFAULT);
73     }
74 
StateView(Context context, int type)75     public StateView(Context context, int type) {
76         super(context);
77         mType = type;
78         Resources res = getResources();
79         mEndsBackgroundColor = res.getColor(R.color.filtershow_stateview_end_background);
80         mEndsTextColor = res.getColor(R.color.filtershow_stateview_end_text);
81         mBackgroundColor = res.getColor(R.color.filtershow_stateview_background);
82         mTextColor = res.getColor(R.color.filtershow_stateview_text);
83         mSelectedBackgroundColor = res.getColor(R.color.filtershow_stateview_selected_background);
84         mSelectedTextColor = res.getColor(R.color.filtershow_stateview_selected_text);
85         mTextSize = res.getDimensionPixelSize(R.dimen.state_panel_text_size);
86     }
87 
getText()88     public String getText() {
89         return mText;
90     }
91 
setText(String text)92     public void setText(String text) {
93         mText = text;
94         invalidate();
95     }
96 
setType(int type)97     public void setType(int type) {
98         mType = type;
99         invalidate();
100     }
101 
102     @Override
setSelected(boolean value)103     public void setSelected(boolean value) {
104         super.setSelected(value);
105         if (!value) {
106             mDuplicateButton = false;
107         }
108         invalidate();
109     }
110 
drawText(Canvas canvas)111     public void drawText(Canvas canvas) {
112         if (mText == null) {
113             return;
114         }
115         mPaint.reset();
116         if (isSelected()) {
117             mPaint.setColor(mSelectedTextColor);
118         } else {
119             mPaint.setColor(mTextColor);
120         }
121         if (mType == BEGIN) {
122             mPaint.setColor(mEndsTextColor);
123         }
124         mPaint.setTypeface(Typeface.DEFAULT_BOLD);
125         mPaint.setAntiAlias(true);
126         mPaint.setTextSize(mTextSize);
127         mPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
128         int x = (canvas.getWidth() - mTextBounds.width()) / 2;
129         int y = mTextBounds.height() + (canvas.getHeight() - mTextBounds.height()) / 2;
130         canvas.drawText(mText, x, y, mPaint);
131     }
132 
onDraw(Canvas canvas)133     public void onDraw(Canvas canvas) {
134         canvas.drawARGB(0, 0, 0, 0);
135         mPaint.reset();
136         mPath.reset();
137 
138         float w = canvas.getWidth();
139         float h = canvas.getHeight();
140         float r = sArrowHeight;
141         float d = sArrowWidth;
142 
143         if (mOrientation == LinearLayout.HORIZONTAL) {
144             drawHorizontalPath(w, h, r, d);
145         } else {
146             if (mDirection == DOWN) {
147                 drawVerticalDownPath(w, h, r, d);
148             } else {
149                 drawVerticalPath(w, h, r, d);
150             }
151         }
152 
153         if (mType == DEFAULT || mType == END) {
154             if (mDuplicateButton) {
155                 mPaint.setARGB(255, 200, 0, 0);
156             } else if (isSelected()) {
157                 mPaint.setColor(mSelectedBackgroundColor);
158             } else {
159                 mPaint.setColor(mBackgroundColor);
160             }
161         } else {
162             mPaint.setColor(mEndsBackgroundColor);
163         }
164         canvas.drawPath(mPath, mPaint);
165         drawText(canvas);
166     }
167 
drawHorizontalPath(float w, float h, float r, float d)168     private void drawHorizontalPath(float w, float h, float r, float d) {
169         if (this.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
170             mPath.moveTo(w, 0);
171             if (mType == END) {
172                 mPath.lineTo(0, 0);
173                 mPath.lineTo(0, h);
174             } else {
175                 mPath.lineTo(d, 0);
176                 mPath.lineTo(d, r);
177                 mPath.lineTo(0, r + d);
178                 mPath.lineTo(d, r + d + r);
179                 mPath.lineTo(d, h);
180             }
181             mPath.lineTo(w, h);
182             if (mType != BEGIN) {
183                 mPath.lineTo(w, r + d + r);
184                 mPath.lineTo(w - d, r + d);
185                 mPath.lineTo(w, r);
186             }
187         } else {
188             mPath.moveTo(0, 0);
189             if (mType == END) {
190                 mPath.lineTo(w, 0);
191                 mPath.lineTo(w, h);
192             } else {
193                 mPath.lineTo(w - d, 0);
194                 mPath.lineTo(w - d, r);
195                 mPath.lineTo(w, r + d);
196                 mPath.lineTo(w - d, r + d + r);
197                 mPath.lineTo(w - d, h);
198             }
199             mPath.lineTo(0, h);
200             if (mType != BEGIN) {
201                 mPath.lineTo(0, r + d + r);
202                 mPath.lineTo(d, r + d);
203                 mPath.lineTo(0, r);
204             }
205         }
206         mPath.close();
207     }
208 
drawVerticalPath(float w, float h, float r, float d)209     private void drawVerticalPath(float w, float h, float r, float d) {
210         if (mType == BEGIN) {
211             mPath.moveTo(0, 0);
212             mPath.lineTo(w, 0);
213         } else {
214             mPath.moveTo(0, d);
215             mPath.lineTo(r, d);
216             mPath.lineTo(r + d, 0);
217             mPath.lineTo(r + d + r, d);
218             mPath.lineTo(w, d);
219         }
220         mPath.lineTo(w, h);
221         if (mType != END) {
222             mPath.lineTo(r + d + r, h);
223             mPath.lineTo(r + d, h - d);
224             mPath.lineTo(r, h);
225         }
226         mPath.lineTo(0, h);
227         mPath.close();
228     }
229 
drawVerticalDownPath(float w, float h, float r, float d)230     private void drawVerticalDownPath(float w, float h, float r, float d) {
231         mPath.moveTo(0, 0);
232         if (mType != BEGIN) {
233             mPath.lineTo(r, 0);
234             mPath.lineTo(r + d, d);
235             mPath.lineTo(r + d + r, 0);
236         }
237         mPath.lineTo(w, 0);
238 
239         if (mType != END) {
240             mPath.lineTo(w, h - d);
241 
242             mPath.lineTo(r + d + r, h - d);
243             mPath.lineTo(r + d, h);
244             mPath.lineTo(r, h - d);
245 
246             mPath.lineTo(0, h - d);
247         } else {
248             mPath.lineTo(w, h);
249             mPath.lineTo(0, h);
250         }
251 
252         mPath.close();
253     }
254 
setBackgroundAlpha(float alpha)255     public void setBackgroundAlpha(float alpha) {
256         if (mType == BEGIN) {
257             return;
258         }
259         mAlpha = alpha;
260         setAlpha(alpha);
261         invalidate();
262     }
263 
getBackgroundAlpha()264     public float getBackgroundAlpha() {
265         return mAlpha;
266     }
267 
setOrientation(int orientation)268     public void setOrientation(int orientation) {
269         mOrientation = orientation;
270     }
271 
setDuplicateButton(boolean b)272     public void setDuplicateButton(boolean b) {
273         mDuplicateButton = b;
274         invalidate();
275     }
276 
getState()277     public State getState() {
278         return mState;
279     }
280 
setState(State state)281     public void setState(State state) {
282         mState = state;
283         mText = mState.getText().toUpperCase();
284         mType = mState.getType();
285         invalidate();
286     }
287 
resetPosition()288     public void resetPosition() {
289         setTranslationX(0);
290         setTranslationY(0);
291         setBackgroundAlpha(1.0f);
292     }
293 
isDraggable()294     public boolean isDraggable() {
295         return mState.isDraggable();
296     }
297 
298     @Override
delete()299     public void delete() {
300         FilterShowActivity activity = (FilterShowActivity) getContext();
301         FilterRepresentation representation = getState().getFilterRepresentation();
302         activity.removeFilterRepresentation(representation);
303     }
304 
305     @Override
onTouchEvent(MotionEvent event)306     public boolean onTouchEvent(MotionEvent event) {
307         boolean ret = super.onTouchEvent(event);
308         FilterShowActivity activity = (FilterShowActivity) getContext();
309 
310         if (event.getActionMasked() == MotionEvent.ACTION_UP) {
311             activity.startTouchAnimation(this, event.getX(), event.getY());
312         }
313         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
314             mStartTouchY = event.getY();
315             mStartTouchX = event.getX();
316             if (mType == BEGIN) {
317                 PrimaryImage.getImage().setShowsOriginal(true);
318             }
319         }
320         if (event.getActionMasked() == MotionEvent.ACTION_UP
321             || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
322             setTranslationX(0);
323             setTranslationY(0);
324             PrimaryImage.getImage().setShowsOriginal(false);
325             if (mType != BEGIN && event.getActionMasked() == MotionEvent.ACTION_UP) {
326                 setSelected(true);
327                 FilterRepresentation representation = getState().getFilterRepresentation();
328                 PrimaryImage image = PrimaryImage.getImage();
329                 ImagePreset preset = image != null ? image.getCurrentPreset() : null;
330                 if (getTranslationY() == 0
331                         && image != null && preset != null
332                         && representation != image.getCurrentFilterRepresentation()
333                         && preset.getRepresentation(representation) != null) {
334                     activity.showRepresentation(representation);
335                     setSelected(false);
336                 }
337             }
338         }
339         if (mType != BEGIN && event.getActionMasked() == MotionEvent.ACTION_MOVE) {
340             float delta = event.getY() - mStartTouchY;
341             if (Math.abs(delta) > mDeleteSlope) {
342                 activity.setHandlesSwipeForView(this, mStartTouchX, mStartTouchY);
343             }
344         }
345         return true;
346     }
347 }
348