/* * Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com> * * This file is part of Loop Habit Tracker. * * Loop Habit Tracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * Loop Habit Tracker is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.isoron.uhabits.widgets; import android.app.*; import android.content.*; import android.graphics.*; import android.support.annotation.*; import android.view.*; import android.widget.*; import org.isoron.uhabits.*; import org.isoron.uhabits.intents.*; import org.isoron.uhabits.preferences.*; import static android.os.Build.VERSION.*; import static android.os.Build.VERSION_CODES.*; import static android.view.View.MeasureSpec.*; public abstract class BaseWidget { private final WidgetPreferences prefs; private final int id; @NonNull private WidgetDimensions dimensions; @NonNull private final Context context; protected final PendingIntentFactory pendingIntentFactory; public BaseWidget(@NonNull Context context, int id) { this.id = id; this.context = context; HabitsApplication app = (HabitsApplication) context.getApplicationContext(); prefs = app.getComponent().getWidgetPreferences(); pendingIntentFactory = app.getComponent().getPendingIntentFactory(); dimensions = new WidgetDimensions(getDefaultWidth(), getDefaultHeight(), getDefaultWidth(), getDefaultHeight()); } public void delete() { prefs.removeWidget(id); } @NonNull public Context getContext() { return context; } public int getId() { return id; } @NonNull public RemoteViews getLandscapeRemoteViews() { return getRemoteViews(dimensions.getLandscapeWidth(), dimensions.getLandscapeHeight()); } public abstract PendingIntent getOnClickPendingIntent(Context context); @NonNull public RemoteViews getPortraitRemoteViews() { return getRemoteViews(dimensions.getPortraitWidth(), dimensions.getPortraitHeight()); } public abstract void refreshData(View widgetView); public void setDimensions(@NonNull WidgetDimensions dimensions) { this.dimensions = dimensions; } protected abstract View buildView(); protected abstract int getDefaultHeight(); protected abstract int getDefaultWidth(); private void adjustRemoteViewsPadding(RemoteViews remoteViews, View view, int width, int height) { int imageWidth = view.getMeasuredWidth(); int imageHeight = view.getMeasuredHeight(); int p[] = calculatePadding(width, height, imageWidth, imageHeight); remoteViews.setViewPadding(R.id.buttonOverlay, p[0], p[1], p[2], p[3]); } private void buildRemoteViews(View view, RemoteViews remoteViews, int width, int height) { Bitmap bitmap = getBitmapFromView(view); remoteViews.setImageViewBitmap(R.id.imageView, bitmap); if (SDK_INT >= JELLY_BEAN) adjustRemoteViewsPadding(remoteViews, view, width, height); PendingIntent onClickIntent = getOnClickPendingIntent(context); if (onClickIntent != null) remoteViews.setOnClickPendingIntent(R.id.button, onClickIntent); } private int[] calculatePadding(int entireWidth, int entireHeight, int imageWidth, int imageHeight) { int w = (int) (((float) entireWidth - imageWidth) / 2); int h = (int) (((float) entireHeight - imageHeight) / 2); return new int[]{ w, h, w, h }; } @NonNull private Bitmap getBitmapFromView(View view) { view.invalidate(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(true); Bitmap drawingCache = view.getDrawingCache(); if(drawingCache == null) throw new IllegalStateException("bitmap is null"); return drawingCache; } @NonNull private RemoteViews getRemoteViews(int width, int height) { View view = buildView(); measureView(view, width, height); refreshData(view); if (view.isLayoutRequested()) measureView(view, width, height); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_wrapper); buildRemoteViews(view, remoteViews, width, height); return remoteViews; } private void measureView(View view, int width, int height) { LayoutInflater inflater = LayoutInflater.from(context); View entireView = inflater.inflate(R.layout.widget_wrapper, null); int specWidth = makeMeasureSpec(width, View.MeasureSpec.EXACTLY); int specHeight = makeMeasureSpec(height, View.MeasureSpec.EXACTLY); entireView.measure(specWidth, specHeight); entireView.layout(0, 0, entireView.getMeasuredWidth(), entireView.getMeasuredHeight()); View imageView = entireView.findViewById(R.id.imageView); width = imageView.getMeasuredWidth(); height = imageView.getMeasuredHeight(); specWidth = makeMeasureSpec(width, View.MeasureSpec.EXACTLY); specHeight = makeMeasureSpec(height, View.MeasureSpec.EXACTLY); view.measure(specWidth, specHeight); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); } }