1package com.android.launcher3;
2
3import android.annotation.TargetApi;
4import android.appwidget.AppWidgetHostView;
5import android.appwidget.AppWidgetProviderInfo;
6import android.content.ComponentName;
7import android.content.Context;
8import android.content.pm.PackageManager;
9import android.graphics.Point;
10import android.graphics.Rect;
11import android.graphics.drawable.Drawable;
12import android.os.Build;
13import android.os.Parcel;
14
15/**
16 * This class is a thin wrapper around the framework AppWidgetProviderInfo class. This class affords
17 * a common object for describing both framework provided AppWidgets as well as custom widgets
18 * (who's implementation is owned by the launcher). This object represents a widget type / class,
19 * as opposed to a widget instance, and so should not be confused with {@link LauncherAppWidgetInfo}
20 */
21public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
22
23    public boolean isCustomWidget = false;
24
25    public int spanX;
26    public int spanY;
27    public int minSpanX;
28    public int minSpanY;
29
30    public static LauncherAppWidgetProviderInfo fromProviderInfo(Context context,
31            AppWidgetProviderInfo info) {
32
33        // In lieu of a public super copy constructor, we first write the AppWidgetProviderInfo
34        // into a parcel, and then construct a new LauncherAppWidgetProvider info from the
35        // associated super parcel constructor. This allows us to copy non-public members without
36        // using reflection.
37        Parcel p = Parcel.obtain();
38        info.writeToParcel(p, 0);
39        p.setDataPosition(0);
40        LauncherAppWidgetProviderInfo lawpi = new LauncherAppWidgetProviderInfo(p);
41        p.recycle();
42        return lawpi;
43    }
44
45    public LauncherAppWidgetProviderInfo(Parcel in) {
46        super(in);
47        initSpans();
48    }
49
50    public LauncherAppWidgetProviderInfo(Context context, CustomAppWidget widget) {
51        isCustomWidget = true;
52
53        provider = new ComponentName(context, widget.getClass().getName());
54        icon = widget.getIcon();
55        label = widget.getLabel();
56        previewImage = widget.getPreviewImage();
57        initialLayout = widget.getWidgetLayout();
58        resizeMode = widget.getResizeMode();
59        initSpans();
60    }
61
62    public void initSpans() {
63        LauncherAppState app = LauncherAppState.getInstance();
64        InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
65
66        Point paddingLand = idp.landscapeProfile.getTotalWorkspacePadding();
67        Point paddingPort = idp.portraitProfile.getTotalWorkspacePadding();
68
69        // Always assume we're working with the smallest span to make sure we
70        // reserve enough space in both orientations.
71        float smallestCellWidth = DeviceProfile.calculateCellWidth(Math.min(
72                idp.landscapeProfile.widthPx - paddingLand.x,
73                idp.portraitProfile.widthPx - paddingPort.x),
74                idp.numColumns);
75        float smallestCellHeight = DeviceProfile.calculateCellWidth(Math.min(
76                idp.landscapeProfile.heightPx - paddingLand.y,
77                idp.portraitProfile.heightPx - paddingPort.y),
78                idp.numRows);
79
80        // We want to account for the extra amount of padding that we are adding to the widget
81        // to ensure that it gets the full amount of space that it has requested.
82        Rect widgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(
83                app.getContext(), provider, null);
84        spanX = Math.max(1, (int) Math.ceil(
85                        (minWidth + widgetPadding.left + widgetPadding.right) / smallestCellWidth));
86        spanY = Math.max(1, (int) Math.ceil(
87                (minHeight + widgetPadding.top + widgetPadding.bottom) / smallestCellHeight));
88
89        minSpanX = Math.max(1, (int) Math.ceil(
90                (minResizeWidth + widgetPadding.left + widgetPadding.right) / smallestCellWidth));
91        minSpanY = Math.max(1, (int) Math.ceil(
92                (minResizeHeight + widgetPadding.top + widgetPadding.bottom) / smallestCellHeight));
93    }
94
95    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
96    public String getLabel(PackageManager packageManager) {
97        if (isCustomWidget) {
98            return Utilities.trim(label);
99        }
100        return super.loadLabel(packageManager);
101    }
102
103    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
104    public Drawable getIcon(Context context, IconCache cache) {
105        if (isCustomWidget) {
106            return cache.getFullResIcon(provider.getPackageName(), icon);
107        }
108        return super.loadIcon(context,
109                LauncherAppState.getInstance().getInvariantDeviceProfile().fillResIconDpi);
110    }
111
112    public String toString(PackageManager pm) {
113        if (isCustomWidget) {
114            return "WidgetProviderInfo(" + provider + ")";
115        }
116        return String.format("WidgetProviderInfo provider:%s package:%s short:%s label:%s",
117                provider.toString(), provider.getPackageName(), provider.getShortClassName(), getLabel(pm));
118    }
119
120    public Point getMinSpans(InvariantDeviceProfile idp, Context context) {
121        return new Point(
122                (resizeMode & RESIZE_HORIZONTAL) != 0 ? minSpanX : -1,
123                        (resizeMode & RESIZE_VERTICAL) != 0 ? minSpanY : -1);
124    }
125 }
126