/* * Copyright © 2014 Jeff Corcoran * * This file is part of Hangar. * * Hangar 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. * * Hangar 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 Hangar. If not, see <http://www.gnu.org/licenses/>. * */ package ca.mimic.apphangar; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; import android.view.View; import android.widget.RemoteViews; import java.util.ArrayList; import ca.mimic.apphangar.Settings.PrefsGet; public class AppsWidget extends AppWidgetProvider { protected static final int SMALL_ICONS = 0; protected static final int LARGE_ICONS = 2; protected static final int ICON_SMALL_HEIGHT = 40; protected static final int ICON_SMALL_WIDTH = 36; protected static final int ICON_MEDIUM_HEIGHT = 54; protected static final int ICON_MEDIUM_WIDTH = 50; protected static final int ICON_LARGE_HEIGHT = 70; protected static final int ICON_LARGE_WIDTH = 64; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Tools.HangarLog("onUpdate [" + this.getClass().getCanonicalName() + "]"); // (re?)start service. This is specifically so if hangar gets updated the service // is restarted Intent intent = new Intent(context, WatchfulService.class); context.startService(intent); } @Override public void onReceive(Context context, Intent intent) { Tools.HangarLog("onReceive [" + this.getClass().getCanonicalName() + "]"); AppWidgetManager mgr = AppWidgetManager.getInstance(context); int[] ids = mgr.getAppWidgetIds(new ComponentName(context, AppsWidget.class)); for(int id : ids) { Tools.HangarLog("per id: " + id); try { Bundle options=mgr.getAppWidgetOptions(id); updateAppWidget(context, mgr, id, options); } catch (Exception e) { e.printStackTrace(); Tools.HangarLog("NPE onReceive"); } } super.onReceive(context, intent); } static int findDimensions(int widgetDimension, int itemDimension) { return (int) Math.floor(widgetDimension / itemDimension); } void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle options) { Tools.HangarLog("updateAppWidget (AppsWidget)"); PrefsGet prefs = new PrefsGet(context.getSharedPreferences("AppsWidget", Context.MODE_PRIVATE)); SharedPreferences mPrefs = prefs.prefsGet(); int rowLayout = R.layout.apps_widget_row; int itemLayout = R.layout.apps_widget_item; int itemHeight = ICON_MEDIUM_HEIGHT; int itemWidth = ICON_MEDIUM_WIDTH; final int TOP_ROW = 1; final int BOT_ROW = 2; int iconSize = Integer.parseInt(mPrefs.getString(Settings.ICON_SIZE_PREFERENCE, Integer.toString(Settings.ICON_SIZE_DEFAULT))); int mGravity = Integer.parseInt(mPrefs.getString(Settings.ALIGNMENT_PREFERENCE, Integer.toString(Settings.ALIGNMENT_DEFAULT))); // setSize switch (iconSize) { case SMALL_ICONS: rowLayout = R.layout.apps_widget_row_small; itemHeight = ICON_SMALL_HEIGHT; itemWidth = ICON_SMALL_WIDTH; break; case LARGE_ICONS: rowLayout = R.layout.apps_widget_row_large; itemHeight = ICON_LARGE_HEIGHT; itemWidth = ICON_LARGE_WIDTH; break; } boolean appsNoByWidgetSize = mPrefs.getBoolean(Settings.APPS_BY_WIDGET_SIZE_PREFERENCE, Settings.APPS_BY_WIDGET_SIZE_DEFAULT); int appsNoH; int appsNoW; boolean autoHeight = true; Tools.HangarLog("minHeight: " + options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)); Tools.HangarLog("maxHeight: " + options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)); Tools.HangarLog("minWidth: " + options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)); Tools.HangarLog("maxWidth: " + options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)); appsNoH = findDimensions(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT), itemHeight); appsNoW = findDimensions(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH), itemWidth); Tools.HangarLog("appsNoH: " + appsNoH + " appsNoW: " + appsNoW); if (appsNoH == 0) { appsNoH = 1; autoHeight = false; } if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ float widgetHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); appsNoH = findDimensions((int) widgetHeight, itemHeight); int origWidgetHeight = appsNoH; if (iconSize > SMALL_ICONS) { if (iconSize == LARGE_ICONS) { appsNoH = findDimensions(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT), itemHeight); if (appsNoH == 0 && widgetHeight > 0) { Tools.HangarLog("Widget height > 0 but < 1 for iconSize. Setting lower size"); rowLayout = R.layout.apps_widget_row; itemWidth = ICON_MEDIUM_WIDTH; } } // Are we medium (either originally or via the above if? if (itemWidth == ICON_MEDIUM_WIDTH) { appsNoH = findDimensions(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT), ICON_MEDIUM_HEIGHT); if (appsNoH == 0 && widgetHeight > 0) { Tools.HangarLog("Widget height > 0 but < 1 for iconSize. Setting lower size"); rowLayout = R.layout.apps_widget_row_small; itemWidth = ICON_SMALL_WIDTH; // Get rid of the alignment wonkiness when forcing small icons mGravity = Settings.ALIGNMENT_DEFAULT; } } } if (origWidgetHeight == 0) { appsNoH = 1; autoHeight = false; } appsNoW = findDimensions(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH), itemWidth); if (appsNoByWidgetSize && appsNoW > 0) { Tools.HangarLog("Landscape! appsNoByWidgetSize=true, appsNo=" + appsNoW); } else { appsNoW = Integer.parseInt(mPrefs.getString(Settings.STATS_WIDGET_APPSNO_LS_PREFERENCE, Integer.toString(Settings.APPS_WIDGET_APPSNO_LS_DEFAULT))); } Tools.HangarLog("LANDSCAPE"); } else { if (appsNoByWidgetSize && appsNoW > 0) { Tools.HangarLog("appsNoByWidgetSize=true, appsNo=" + appsNoH); } else { appsNoW = Integer.parseInt(mPrefs.getString(Settings.STATS_WIDGET_APPSNO_PREFERENCE, Integer.toString(Settings.APPS_WIDGET_APPSNO_DEFAULT))); } } int getBackgroundColor = mPrefs.getInt(Settings.BACKGROUND_COLOR_PREFERENCE, Settings.BACKGROUND_COLOR_DEFAULT); RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.apps_widget); views.setInt(R.id.viewCont, "setGravity", mGravity); TasksDataSource db = TasksDataSource.getInstance(context); db.open(); int gridSize = (appsNoH * appsNoW); // numOfIcons should not exceed 35 (CPU reasons, etc) int numOfIcons = (appsNoH * appsNoW > Settings.TASKLIST_QUEUE_SIZE) ? Settings.TASKLIST_QUEUE_SIZE : (appsNoH * appsNoW); if (autoHeight && !appsNoByWidgetSize) { // Manual app # is selected. Icons are split automatically from height. numOfIcons = appsNoW; } int queueSize = (Math.ceil(numOfIcons * 1.2f)) < Settings.APPLIST_QUEUE_SIZE ? Settings.APPLIST_QUEUE_SIZE : (int) Math.ceil(numOfIcons * 1.2f); String taskPackage = context.getPackageName(); boolean weightedRecents = mPrefs.getBoolean(Settings.WEIGHTED_RECENTS_PREFERENCE, Settings.WEIGHTED_RECENTS_DEFAULT); ArrayList<Tools.TaskInfo> appList = Tools.buildTaskList(context, db, queueSize, weightedRecents, true); boolean ignorePinned = mPrefs.getBoolean(Settings.IGNORE_PINNED_PREFERENCE, Settings.IGNORE_PINNED_DEFAULT); if (!ignorePinned) { ArrayList<Tools.TaskInfo> pinnedList = Tools.buildPinnedList(context, db); appList = new Tools().getPinnedTasks(context, pinnedList, appList, numOfIcons, false); } db.close(); int imageButtonLayout = context.getResources().getIdentifier("imageButton", "id", taskPackage); int imageContLayout = context.getResources().getIdentifier("imageCont", "id", taskPackage); AppDrawer appDrawer = new AppDrawer(taskPackage); appDrawer.createRow(rowLayout, R.id.viewRow); appDrawer.setImageLayouts(imageButtonLayout, imageContLayout); appDrawer.setPrefs(mPrefs); appDrawer.setContext(context); appDrawer.setRowBackgroundColor(getBackgroundColor, TOP_ROW); appDrawer.setCount(numOfIcons, Settings.TASKLIST_QUEUE_SIZE, true); if (autoHeight && !appsNoByWidgetSize) { appsNoW = (int) Math.ceil((double) appsNoW / appsNoH); Tools.HangarLog("autoHeight true (start), appsNoW=" + appsNoW); } int filledConts = 0; int filledRows = 1; Tools.HangarLog("appsNoW: " + appsNoW + " appList.size(): " + appList.size() + " numOfIcons: " + numOfIcons); views.removeAllViews(R.id.viewCont); for (int i=0; i <= gridSize; i++) { if (filledConts == appsNoW || i == gridSize) { Tools.HangarLog("i: " + i + " filledConts: " + filledConts); views.addView(R.id.viewCont, appDrawer.getRow()); if (i >= numOfIcons && !appsNoByWidgetSize) break; boolean lineBreak = (appsNoByWidgetSize && appList.size() > i) || (!appsNoByWidgetSize && numOfIcons > i); if (filledRows < appsNoH && filledConts < numOfIcons && lineBreak) { appDrawer.createRow(rowLayout, R.id.viewRow); appDrawer.setRowBackgroundColor(getBackgroundColor); filledConts = 0; filledRows++; } else { break; } } Tools.TaskInfo newItemTask; if (i >= appList.size()) { newItemTask = new Tools.TaskInfo(null); } else { newItemTask = appList.get(i); } boolean newItem = appDrawer.newItem(newItemTask, itemLayout); if (!newItem) { numOfIcons++; continue; } filledConts += 1; if (i >= numOfIcons || i >= appList.size()) { appDrawer.setItemVisibility(View.INVISIBLE); appDrawer.addItem(); continue; } appDrawer.addItem(); } // Last row is bottom row appDrawer.setRowBackgroundColor(getBackgroundColor, BOT_ROW); // Instruct the widget manager to update the widget appWidgetManager.updateAppWidget(appWidgetId, views); } }