/* * Copyright (C) 2015 AChep@xda <artemchep@gmail.com> * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package com.achep.acdisplay.ui.components; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.achep.acdisplay.Config; import com.achep.acdisplay.R; import com.achep.acdisplay.appwidget.MyAppWidgetHost; import com.achep.acdisplay.appwidget.MyAppWidgetHostView; import com.achep.acdisplay.ui.fragments.AcDisplayFragment; import com.achep.base.content.ConfigBase; import com.achep.base.utils.AppWidgetUtils; import com.achep.base.utils.MathUtils; import com.achep.base.utils.ViewUtils; /** * A widget the hosts {@link android.appwidget.AppWidgetHost}. * * @author Artem Chepurnoy */ public class HostWidget extends Widget implements ConfigBase.OnConfigChangedListener { private static final String TAG = "HostWidget"; public static final int HOST_ID = 1; private final AppWidgetManager mAppWidgetManager; private final MyAppWidgetHost mAppWidgetHost; private MyAppWidgetHostView mHostView; private ViewGroup mHostContainer; private View mEmptyView; private boolean mHostViewNeedsReInflate; public HostWidget(@NonNull Callback callback, @NonNull AcDisplayFragment fragment) { super(callback, fragment); Activity activity = fragment.getActivity(); mAppWidgetManager = AppWidgetManager.getInstance(activity); mAppWidgetHost = new MyAppWidgetHost(activity, HOST_ID); } @Override public void onStart() { super.onStart(); mAppWidgetHost.startListening(); getConfig().registerListener(this); updateAppWidgetViewIfNeeded(); } @Override public void onViewAttached() { super.onViewAttached(); updateAppWidgetViewIfNeeded(); } @Override public void onStop() { getConfig().unregisterListener(this); mAppWidgetHost.stopListening(); mHostViewNeedsReInflate = true; // Stopping listening removes all active views from it, // so we will have to re-inflate them. super.onStop(); } /** * {@inheritDoc} */ @Override public boolean isHomeWidget() { return true; } /** * {@inheritDoc} */ @Override public boolean hasClock() { return true; } @Override protected ViewGroup onCreateView( @NonNull LayoutInflater inflater, @NonNull ViewGroup container, @Nullable ViewGroup sceneView) { boolean initialize = sceneView == null; if (initialize) { sceneView = (ViewGroup) inflater.inflate(R.layout.acdisplay_scene_host, container, false); assert sceneView != null; } mHostContainer = (ViewGroup) sceneView.findViewById(R.id.scene); mEmptyView = sceneView.findViewById(R.id.empty); return sceneView; } @Nullable @Override public Bitmap getBackground() { return null; } @Override public int getBackgroundMask() { return 0; } //-- APP WIDGET HOST ------------------------------------------------------ private void updateAppWidgetViewIfNeeded() { if (!isStarted() || !isViewAttached()) return; int id = getConfig().getCustomWidgetId(); if (!AppWidgetUtils.isValidId(id)) { if (mHostView != null) { ViewUtils.removeViewParent(mHostView); mEmptyView.setVisibility(View.VISIBLE); mHostViewNeedsReInflate = false; mHostView = null; } return; } Context context = getFragment().getActivity(); if (mHostView == null) { mHostView = new MyAppWidgetHostView(context); updateAppWidgetTouchable(); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL); mHostContainer.addView(mHostView, lp); mEmptyView.setVisibility(View.GONE); } else if (!mHostViewNeedsReInflate && mHostView.getAppWidgetId() == id) return; AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(id); mAppWidgetHost.updateView(context, id, appWidget, mHostView); mHostViewNeedsReInflate = false; updateAppWidgetFrameSize(); } private void updateAppWidgetFrameSize() { Resources res = getFragment().getActivity().getResources(); int h = getConfig().getCustomWidgetHeightDp(); int hMin = res.getDimensionPixelSize(R.dimen.scene_min_height); int hMax = res.getDimensionPixelSize(R.dimen.scene_max_height); int w = getConfig().getCustomWidgetWidthDp(); int wMin = res.getDimensionPixelSize(R.dimen.scene_min_width); int wMax = res.getDimensionPixelSize(R.dimen.scene_max_width); float density = res.getDisplayMetrics().density; w = Math.round(MathUtils.range(w * density, wMin, wMax)); h = Math.round(MathUtils.range(h * density, hMin, hMax)); // Update size ViewUtils.setSize(mHostView, w, h); mHostView.updateAppWidgetSize(null, w, h, w, h); } private void updateAppWidgetTouchable() { mHostView.setTouchable(getConfig().isCustomWidgetTouchable()); } /** * {@inheritDoc} */ @Override public void onConfigChanged(@NonNull ConfigBase config, @NonNull String key, @NonNull Object value) { switch (key) { case Config.KEY_UI_CUSTOM_WIDGET_ID: mHostViewNeedsReInflate = true; updateAppWidgetViewIfNeeded(); break; case Config.KEY_UI_CUSTOM_WIDGET_WIDTH_DP: case Config.KEY_UI_CUSTOM_WIDGET_HEIGHT_DP: if (mHostView != null) updateAppWidgetFrameSize(); break; case Config.KEY_UI_CUSTOM_WIDGET_TOUCHABLE: if (mHostView != null) updateAppWidgetTouchable(); break; } } }