129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung/*
23f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song * Copyright (C) 2015 The Android Open Source Project
329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung *
429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * you may not use this file except in compliance with the License.
629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * You may obtain a copy of the License at
729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung *
829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung *
1029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * Unless required by applicable law or agreed to in writing, software
1129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
1229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * See the License for the specific language governing permissions and
1429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * limitations under the License.
1529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung */
1629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpackage com.android.launcher3.widget;
1829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
1929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.content.Context;
2059e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chungimport android.content.res.Resources;
215b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyalimport android.graphics.Bitmap;
2229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.util.AttributeSet;
233f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport android.util.Log;
24ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellorimport android.view.MotionEvent;
25ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohenimport android.view.View;
265b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyalimport android.view.View.OnLayoutChangeListener;
27f00d02b254d94eeaf52742e0640e9eacd63fafcaHyunyoung Songimport android.view.ViewPropertyAnimator;
2829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.widget.LinearLayout;
2929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.widget.TextView;
3029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
313f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.DeviceProfile;
323f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.ItemInfo;
332e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohenimport com.android.launcher3.Launcher;
343f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.LauncherAppState;
35bb83520a620919a8f19472ba4426585d007d1abaMady Mellorimport com.android.launcher3.SimpleOnStylusPressListener;
363f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.R;
37ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellorimport com.android.launcher3.StylusEventHelper;
383f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songimport com.android.launcher3.WidgetPreviewLoader;
395b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyalimport com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
404ddc40130aa0460924364eab3557088421eebe0cSunny Goyalimport com.android.launcher3.model.WidgetItem;
41ffe83f13319cdb833a25596d47cf1af098cc4c60Sunny Goyal
4229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung/**
43f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * Represents the individual cell of the widget inside the widget tray. The preview is drawn
44f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * horizontally centered, and scaled down if needed.
45f52abd7758b8f245522936e941336e574debabf5Sunny Goyal *
46f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * This view does not support padding. Since the image is scaled down to fit the view, padding will
47f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * further decrease the scaling factor. Drag-n-drop uses the view bounds for showing a smooth
48f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * transition from the view to drag view, so when adding padding support, DnD would need to
49f52abd7758b8f245522936e941336e574debabf5Sunny Goyal * consider the appropriate scaling factor.
5029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung */
513f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Songpublic class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
5229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
534e8fb91cf19b7d621de8cbed2bde2c8dac734121Hyunyoung Song    private static final String TAG = "WidgetCell";
543f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    private static final boolean DEBUG = false;
553f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
56f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song    private static final int FADE_IN_DURATION_MS = 90;
574b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song
584b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song    /** Widget cell width is calculated by multiplying this factor to grid cell width. */
595cd1d92f6c40b47eff12859d4e13b6431aa778c0Hyunyoung Song    private static final float WIDTH_SCALE = 2.6f;
604b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song
614b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song    /** Widget preview width is calculated by multiplying this factor to the widget cell width. */
625cd1d92f6c40b47eff12859d4e13b6431aa778c0Hyunyoung Song    private static final float PREVIEW_SCALE = 0.8f;
634b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song
645cd1d92f6c40b47eff12859d4e13b6431aa778c0Hyunyoung Song    private int mPresetPreviewSize;
655cd1d92f6c40b47eff12859d4e13b6431aa778c0Hyunyoung Song    int cellSize;
663f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
67f52abd7758b8f245522936e941336e574debabf5Sunny Goyal    private WidgetImageView mWidgetImage;
68b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song    private TextView mWidgetName;
69b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song    private TextView mWidgetDims;
705b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal
714ddc40130aa0460924364eab3557088421eebe0cSunny Goyal    private WidgetItem mItem;
725b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal
733f4e070aa58d51dd136885b4d3e2e6c5d9f93ea0Michael Jurka    private WidgetPreviewLoader mWidgetPreviewLoader;
745b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    private PreviewLoadRequest mActiveRequest;
75ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor    private StylusEventHelper mStylusEventHelper;
760499834db3f9dc6fb0f5f57b5876b8503bce5189Winson Chung
774ddc40130aa0460924364eab3557088421eebe0cSunny Goyal    private final Launcher mLauncher;
782e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen
793f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public WidgetCell(Context context) {
8029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung        this(context, null);
8129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung    }
8229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
833f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public WidgetCell(Context context, AttributeSet attrs) {
8429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung        this(context, attrs, 0);
8529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung    }
8629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
873f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    public WidgetCell(Context context, AttributeSet attrs, int defStyle) {
8829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung        super(context, attrs, defStyle);
8929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
9059e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chung        final Resources r = context.getResources();
91abef55a1c1f1fda4f42e4b4223534dd21f3dc19fAndrew Sapperstein        mLauncher = Launcher.getLauncher(context);
92bb83520a620919a8f19472ba4426585d007d1abaMady Mellor        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
9359e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chung
944b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song        setContainerWidth();
9529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung        setWillNotDraw(false);
9629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung        setClipToPadding(false);
97ae50284e0a838139c67caf0064a0977c871497faSunny Goyal        setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
984b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song    }
993f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
1004b69f2ca91d63a59dfa921ba965b92de7f604f5aHyunyoung Song    private void setContainerWidth() {
1012e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        DeviceProfile profile = mLauncher.getDeviceProfile();
1025cd1d92f6c40b47eff12859d4e13b6431aa778c0Hyunyoung Song        cellSize = (int) (profile.cellWidthPx * WIDTH_SCALE);
1032e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        mPresetPreviewSize = (int) (cellSize * PREVIEW_SCALE);
10429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung    }
10529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung
106c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung    @Override
107c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung    protected void onFinishInflate() {
108c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung        super.onFinishInflate();
109c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung
110f52abd7758b8f245522936e941336e574debabf5Sunny Goyal        mWidgetImage = (WidgetImageView) findViewById(R.id.widget_preview);
111b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song        mWidgetName = ((TextView) findViewById(R.id.widget_name));
112b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song        mWidgetDims = ((TextView) findViewById(R.id.widget_dims));
1134e8fb91cf19b7d621de8cbed2bde2c8dac734121Hyunyoung Song    }
1144e8fb91cf19b7d621de8cbed2bde2c8dac734121Hyunyoung Song
115559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song    /**
116559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song     * Called to clear the view and free attached resources. (e.g., {@link Bitmap}
117559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song     */
118559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song    public void clear() {
119559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song        if (DEBUG) {
120559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song            Log.d(TAG, "reset called on:" + mWidgetName.getText());
121559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song        }
1222d58471e8d3da621e209cec58a43d159778f8a0eWinson Chung        mWidgetImage.animate().cancel();
123f52abd7758b8f245522936e941336e574debabf5Sunny Goyal        mWidgetImage.setBitmap(null);
124b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song        mWidgetName.setText(null);
125b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song        mWidgetDims.setText(null);
126f17a1c9ad99d46a65de797422fd439382114b348Hyunyoung Song
127559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song        if (mActiveRequest != null) {
128559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song            mActiveRequest.cleanup();
129559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song            mActiveRequest = null;
130559d90d0dafbac1d97a1e6f18062309831a25d51Hyunyoung Song        }
131099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung    }
132099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung
1334ddc40130aa0460924364eab3557088421eebe0cSunny Goyal    public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) {
1344ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        mItem = item;
1354ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        mWidgetName.setText(mItem.label);
1364ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        mWidgetDims.setText(getContext().getString(R.string.widget_dims_format,
1374ddc40130aa0460924364eab3557088421eebe0cSunny Goyal                mItem.spanX, mItem.spanY));
1386c61323998edccbc28dc9f31602594e4f32e1215Jon Miranda        mWidgetDims.setContentDescription(getContext().getString(
1396c61323998edccbc28dc9f31602594e4f32e1215Jon Miranda                R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
140d31dcbcc7c7901959c65c4e635e59274a1d4c334Hyunyoung Song        mWidgetPreviewLoader = loader;
141d31dcbcc7c7901959c65c4e635e59274a1d4c334Hyunyoung Song
1424ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        if (item.activityInfo != null) {
1434ddc40130aa0460924364eab3557088421eebe0cSunny Goyal            setTag(new PendingAddShortcutInfo(item.activityInfo));
1444ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        } else {
1454ddc40130aa0460924364eab3557088421eebe0cSunny Goyal            setTag(new PendingAddWidgetInfo(mLauncher, item.widgetInfo));
1464ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        }
147b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chung    }
1480499834db3f9dc6fb0f5f57b5876b8503bce5189Winson Chung
149038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    public int[] getPreviewSize() {
150038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        int[] maxSize = new int[2];
1516babf2e27e6260f02751413b8f7a55e46659af27Hyunyoung Song
1523f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        maxSize[0] = mPresetPreviewSize;
1533f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        maxSize[1] = mPresetPreviewSize;
154038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka        return maxSize;
155038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka    }
156038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka
1575b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    public void applyPreview(Bitmap bitmap) {
158f52abd7758b8f245522936e941336e574debabf5Sunny Goyal        if (bitmap != null) {
159f52abd7758b8f245522936e941336e574debabf5Sunny Goyal            mWidgetImage.setBitmap(bitmap);
160b99ff3e83270e113f6182e337c4f7b0223bad92bHyunyoung Song            mWidgetImage.setAlpha(0f);
161f00d02b254d94eeaf52742e0640e9eacd63fafcaHyunyoung Song            ViewPropertyAnimator anim = mWidgetImage.animate();
162f00d02b254d94eeaf52742e0640e9eacd63fafcaHyunyoung Song            anim.alpha(1.0f).setDuration(FADE_IN_DURATION_MS);
163ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        }
164ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
165ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
1665b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    public void ensurePreview() {
1675b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        if (mActiveRequest != null) {
1685b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal            return;
1695b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        }
1705b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        int[] size = getPreviewSize();
1713f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        if (DEBUG) {
1723f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            Log.d(TAG, String.format("[tag=%s] ensurePreview (%d, %d):",
1733f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song                    getTagToString(), size[0], size[1]));
1743f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
1754ddc40130aa0460924364eab3557088421eebe0cSunny Goyal        mActiveRequest = mWidgetPreviewLoader.getPreview(mItem, size[0], size[1], this);
1765b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    }
1775b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal
1785b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    @Override
1795b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
1805b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal            int oldTop, int oldRight, int oldBottom) {
1815b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        removeOnLayoutChangeListener(this);
1825b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        ensurePreview();
1835b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    }
1845b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal
1855b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    public int getActualItemWidth() {
1865b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        ItemInfo info = (ItemInfo) getTag();
1875b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        int[] size = getPreviewSize();
1882e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        int cellWidth = mLauncher.getDeviceProfile().cellWidthPx;
1895b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal
1905b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        return Math.min(size[0], info.spanX * cellWidth);
1915b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    }
1923f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song
193ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor    @Override
194ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor    public boolean onTouchEvent(MotionEvent ev) {
195ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor        boolean handled = super.onTouchEvent(ev);
196bb83520a620919a8f19472ba4426585d007d1abaMady Mellor        if (mStylusEventHelper.onMotionEvent(ev)) {
197ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor            return true;
198ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor        }
199ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor        return handled;
200ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor    }
201ef044dd380ac3abf354027750efdc16d5d48ac70Mady Mellor
2023f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    /**
2033f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song     * Helper method to get the string info of the tag.
2043f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song     */
2053f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    private String getTagToString() {
20682b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        if (getTag() instanceof PendingAddWidgetInfo ||
20782b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                getTag() instanceof PendingAddShortcutInfo) {
20882b016cb56540fe26213e817dd0dd668099c8e20Winson Chung            return getTag().toString();
2093f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        }
2103f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        return "";
2113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song    }
2126d02c7a0337d37e5b1c596a4acec0c292a9b7f93Sunny Goyal
2136d02c7a0337d37e5b1c596a4acec0c292a9b7f93Sunny Goyal    @Override
2146d02c7a0337d37e5b1c596a4acec0c292a9b7f93Sunny Goyal    public CharSequence getAccessibilityClassName() {
2156d02c7a0337d37e5b1c596a4acec0c292a9b7f93Sunny Goyal        return WidgetCell.class.getName();
2166d02c7a0337d37e5b1c596a4acec0c292a9b7f93Sunny Goyal    }
21729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung}
218