Added Android code
[wl-app.git] / Android / app / src / main / java / com / moiseum / wolnelektury / view / book / components / ProgressDownloadButton.java
1 package com.moiseum.wolnelektury.view.book.components;
2
3 /**
4  * Created by Piotr Ostrowski on 21.11.2017.
5  */
6
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.content.res.TypedArray;
10 import android.graphics.Bitmap;
11 import android.graphics.BitmapFactory;
12 import android.graphics.Canvas;
13 import android.graphics.Color;
14 import android.graphics.Paint;
15 import android.graphics.PorterDuff;
16 import android.graphics.PorterDuffColorFilter;
17 import android.graphics.Rect;
18 import android.graphics.RectF;
19 import android.graphics.Typeface;
20 import android.util.AttributeSet;
21 import android.view.View;
22
23 import com.moiseum.wolnelektury.R;
24
25 import java.util.Locale;
26
27 public class ProgressDownloadButton extends View {
28
29         private static final int MAX_PROGRESS_VALUE = 100;
30
31         public enum ProgressDownloadButtonState {
32                 STATE_INITIAL {
33                         @Override
34                         public boolean isEnabled() {
35                                 return true;
36                         }
37
38                         @Override
39                         public boolean isDownloaded() {
40                                 return false;
41                         }
42
43                         @Override
44                         public boolean isDeletable() {
45                                 return false;
46                         }
47
48                         @Override
49                         public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
50                                 int posY = getPosY(attributes, height);
51                                 canvas.drawText(attributes.initialText, attributes.paddingStart, posY, attributes.textPaint);
52                                 int top = (height - attributes.iconBitmap.getHeight()) / 2;
53                                 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
54                                                 .bitmapPaint);
55                         }
56                 }, STATE_DOWNLOADING {
57                         @Override
58                         public boolean isEnabled() {
59                                 return false;
60                         }
61
62                         @Override
63                         public boolean isDownloaded() {
64                                 throw new IllegalStateException("This method shall not be called within this state");
65                         }
66
67                         @Override
68                         public boolean isDeletable() {
69                                 return false;
70                         }
71
72                         @Override
73                         public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
74                                 int posY = getPosY(attributes, height);
75                                 String text = String.format(Locale.getDefault(), "%s: %d%%", attributes.loadingText, attributes.currentProgress);
76
77                                 // Draw text to overlap.
78                                 canvas.drawText(text, attributes.paddingStart, posY, attributes.textPaint);
79
80                                 // Draw icon to overlap.
81                                 int top = (height - attributes.iconBitmap.getHeight()) / 2;
82                                 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
83                                                 .bitmapPaint);
84
85                                 // Draw progress
86                                 int currentProgress = attributes.currentProgress;
87                                 if (currentProgress >= 0 && currentProgress <= MAX_PROGRESS_VALUE) {
88                                         attributes.baseRect.right = attributes.baseRect.width() * currentProgress / MAX_PROGRESS_VALUE;
89                                         canvas.clipRect(attributes.baseRect);
90                                 }
91
92                                 // Draw current state.
93                                 canvas.drawRoundRect(attributes.outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
94                                 canvas.drawText(text, attributes.paddingStart, posY, attributes.invertedPaint);
95                                 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
96                                                 .bitmapInvertedPaint);
97                         }
98                 }, STATE_READING {
99                         @Override
100                         public boolean isEnabled() {
101                                 return true;
102                         }
103
104                         @Override
105                         public boolean isDownloaded() {
106                                 return true;
107                         }
108
109                         @Override
110                         public boolean isDeletable() {
111                                 return true;
112                         }
113
114                         @Override
115                         public void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height) {
116                                 int posY = getPosY(attributes, height);
117                                 int top = (height - attributes.iconBitmap.getHeight()) / 2;
118                                 String text = String.format(Locale.getDefault(), "%1$s: %2$d/%3$d", attributes.downloadedText, attributes
119                                                 .currentReadPosition, attributes.totalReadCount);
120
121                                 canvas.drawRoundRect(attributes.outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
122                                 canvas.drawText(text, attributes.paddingStart, posY, attributes.invertedPaint);
123                                 canvas.drawBitmap(attributes.iconBitmap, width - attributes.iconBitmap.getWidth() - attributes.paddingEnd, top, attributes
124                                                 .bitmapInvertedPaint);
125                         }
126                 };
127
128                 private static int getPosY(ProgressDownloadButtonAttributes attributes, int height) {
129                         return (int) ((height / 2) - ((attributes.textPaint.descent() + attributes.textPaint.ascent()) / 2));
130                 }
131
132                 public abstract boolean isEnabled();
133
134                 public abstract boolean isDownloaded();
135
136                 public abstract boolean isDeletable();
137
138                 public abstract void draw(Canvas canvas, ProgressDownloadButtonAttributes attributes, int width, int height);
139         }
140
141         private static class ProgressDownloadButtonAttributes {
142                 private String initialText = "";
143                 private String downloadedText = "";
144                 private String loadingText;
145
146                 private Rect baseRect = new Rect();
147                 private RectF outerRectF = new RectF();
148                 private RectF innerRectF = new RectF();
149
150                 private int currentProgress = 0;
151                 private int currentReadPosition;
152                 private int totalReadCount;
153
154                 private Paint textPaint;
155                 private Paint invertedPaint;
156                 private Paint bitmapPaint;
157                 private Paint bitmapInvertedPaint;
158
159                 private Bitmap iconBitmap;
160                 private int cornerRadius;
161                 private int innerCornerRadius;
162                 private int borderSize;
163                 private int paddingStart;
164                 private int paddingEnd;
165         }
166
167
168         private ProgressDownloadButtonState currentState = ProgressDownloadButtonState.STATE_INITIAL;
169         private ProgressDownloadButtonAttributes attributes;
170
171         public ProgressDownloadButton(Context context, AttributeSet attrs, int defStyle) {
172                 super(context, attrs, defStyle);
173                 initComponents(context, attrs, defStyle, 0);
174         }
175
176         public ProgressDownloadButton(Context context, AttributeSet attrs) {
177                 super(context, attrs);
178                 initComponents(context, attrs, 0, 0);
179         }
180
181         public ProgressDownloadButton(Context context) {
182                 super(context);
183         }
184
185         //      public InvertedTextProgressbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
186         //              super(context, attrs, defStyleAttr, defStyleRes);
187         //              initComponents(context, attrs, defStyleAttr, defStyleRes);
188         //      }
189
190         /**
191          * Initializes the text paint. This has a fix size.
192          *
193          * @param attrs The XML attributes to use.
194          */
195         @SuppressLint("ResourceType")
196         private void initComponents(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
197                 attributes = new ProgressDownloadButtonAttributes();
198
199                 TypedArray baseAttributes = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.paddingStart, android.R.attr
200                                 .paddingEnd});
201                 TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.ProgressDownloadButton, defStyleAttr, defStyleRes);
202
203                 attributes.paddingStart = baseAttributes.getDimensionPixelOffset(0, 0);
204                 attributes.paddingEnd = baseAttributes.getDimensionPixelOffset(1, 0);
205
206                 Paint textPaint = new Paint();
207                 textPaint.setColor(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_color, Color.BLACK));
208                 textPaint.setStyle(Paint.Style.FILL);
209                 textPaint.setTextSize(styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_text_size, context.getResources()
210                                 .getDimensionPixelSize(R.dimen.download_button_text_size_default)));
211                 textPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
212                 textPaint.setTextAlign(Paint.Align.LEFT); // Text draw is started in the middle
213                 textPaint.setLinearText(true);
214                 textPaint.setAntiAlias(true);
215
216                 // Define the inverted text paint.
217                 Paint invertedPaint = new Paint(textPaint);
218                 invertedPaint.setColor(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_inverted_color, Color.WHITE));
219                 attributes.textPaint = textPaint;
220                 attributes.invertedPaint = invertedPaint;
221
222                 // Define paint for drawable
223                 Paint bitmapPaint = new Paint();
224                 bitmapPaint.setColorFilter(new PorterDuffColorFilter(styledAttributes.getColor(R.styleable.ProgressDownloadButton_text_color,
225                                 Color.BLACK), PorterDuff.Mode.SRC_ATOP));
226                 attributes.bitmapPaint = bitmapPaint;
227
228                 // Define paint for inverted drawable
229                 Paint bitmapInvertedPaint = new Paint();
230                 bitmapInvertedPaint.setColorFilter(new PorterDuffColorFilter(styledAttributes.getColor(R.styleable
231                                 .ProgressDownloadButton_text_inverted_color, Color.WHITE), PorterDuff.Mode.SRC_ATOP));
232                 attributes.bitmapInvertedPaint = bitmapInvertedPaint;
233
234                 // Define the text.
235                 String initialText = styledAttributes.getString(R.styleable.ProgressDownloadButton_text_initial);
236                 if (initialText != null) {
237                         initialText = initialText.toUpperCase();
238                         attributes.initialText = initialText;
239                 }
240                 String downloadedText = styledAttributes.getString(R.styleable.ProgressDownloadButton_text_downloaded);
241                 if (downloadedText != null) {
242                         downloadedText = downloadedText.toUpperCase();
243                         attributes.downloadedText = downloadedText;
244                 }
245                 attributes.loadingText = context.getString(R.string.download_ebook_loading);
246
247                 // Load drawable
248                 attributes.iconBitmap = BitmapFactory.decodeResource(getResources(), styledAttributes.getResourceId(R.styleable
249                                 .ProgressDownloadButton_drawable, android.R.drawable.ic_delete));
250
251                 attributes.borderSize = styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_border_size, context
252                                 .getResources().getDimensionPixelSize(R.dimen.download_button_border_size_default));
253                 attributes.cornerRadius = styledAttributes.getDimensionPixelSize(R.styleable.ProgressDownloadButton_corner_radius, context
254                                 .getResources().getDimensionPixelSize(R.dimen.download_button_corner_radius_default));
255                 attributes.innerCornerRadius = attributes.cornerRadius - attributes.borderSize;
256
257                 // Recycle the TypedArray.
258                 baseAttributes.recycle();
259                 styledAttributes.recycle();
260         }
261
262         @Override
263         protected void onDraw(Canvas canvas) {
264                 canvas.getClipBounds(attributes.baseRect);
265                 RectF outerRectF = attributes.outerRectF;
266                 int borderSize = attributes.borderSize;
267                 outerRectF.set(attributes.baseRect);
268                 attributes.innerRectF.set(outerRectF.left + borderSize, outerRectF.top + borderSize, outerRectF.right - borderSize, outerRectF
269                                 .bottom - borderSize);
270
271                 // Draw outline
272                 canvas.drawRoundRect(outerRectF, attributes.cornerRadius, attributes.cornerRadius, attributes.textPaint);
273                 canvas.drawRoundRect(attributes.innerRectF, attributes.innerCornerRadius, attributes.innerCornerRadius, attributes.invertedPaint);
274
275                 // Draw current state
276                 getState().draw(canvas, attributes, getWidth(), getHeight());
277         }
278
279         public void setState(ProgressDownloadButtonState state) {
280                 this.currentState = state;
281                 this.setEnabled(state.isEnabled());
282                 invalidate();
283         }
284
285         public ProgressDownloadButtonState getState() {
286                 return currentState;
287         }
288
289         /**
290          * Sets the text that will overlay.
291          *
292          * @param text The text to draw.
293          */
294         public void setText(String text) {
295                 attributes.initialText = text;
296         }
297
298         /**
299          * Gets the current text to draw.
300          *
301          * @return The current text to draw.
302          */
303         public String getText() {
304                 return attributes.initialText;
305         }
306
307         public int getCurrentProgress() {
308                 return attributes.currentProgress;
309         }
310
311         public void setProgress(int progress) {
312                 attributes.currentProgress = progress;
313                 invalidate();
314         }
315
316         public void setCurrentReadCount(int position, int count) {
317                 attributes.currentReadPosition = position;
318                 attributes.totalReadCount = count;
319                 invalidate();
320         }
321 }