1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.util 18 19 import android.appwidget.AppWidgetHostView 20 import android.content.Context 21 import android.view.LayoutInflater 22 import android.view.View 23 import android.view.View.OnClickListener 24 import android.view.View.OnFocusChangeListener 25 import android.view.ViewGroup 26 import com.android.launcher3.BubbleTextView 27 import com.android.launcher3.LauncherSettings.Favorites 28 import com.android.launcher3.R 29 import com.android.launcher3.apppairs.AppPairIcon 30 import com.android.launcher3.folder.FolderIcon 31 import com.android.launcher3.model.ModelWriter 32 import com.android.launcher3.model.data.AppPairInfo 33 import com.android.launcher3.model.data.FolderInfo 34 import com.android.launcher3.model.data.ItemInfo 35 import com.android.launcher3.model.data.LauncherAppWidgetInfo 36 import com.android.launcher3.model.data.WorkspaceItemFactory 37 import com.android.launcher3.model.data.WorkspaceItemInfo 38 import com.android.launcher3.views.ActivityContext 39 import com.android.launcher3.widget.LauncherWidgetHolder 40 import com.android.launcher3.widget.PendingAppWidgetHostView 41 import com.android.launcher3.widget.WidgetInflater 42 43 /** Utility class to inflate View for a model item */ 44 class ItemInflater<T>( 45 private val context: T, 46 private val widgetHolder: LauncherWidgetHolder, 47 private val clickListener: OnClickListener, 48 private val focusListener: OnFocusChangeListener, 49 private val defaultParent: ViewGroup 50 ) where T : Context, T : ActivityContext { 51 52 private val widgetInflater = WidgetInflater(context) 53 54 @JvmOverloads inflateItemnull55 fun inflateItem(item: ItemInfo, writer: ModelWriter, nullableParent: ViewGroup? = null): View? { 56 val parent = nullableParent ?: defaultParent 57 when (item.itemType) { 58 Favorites.ITEM_TYPE_APPLICATION, 59 Favorites.ITEM_TYPE_DEEP_SHORTCUT, 60 Favorites.ITEM_TYPE_SEARCH_ACTION -> { 61 var info = 62 if (item is WorkspaceItemFactory) { 63 (item as WorkspaceItemFactory).makeWorkspaceItem(context) 64 } else { 65 item as WorkspaceItemInfo 66 } 67 if (info.container == Favorites.CONTAINER_PREDICTION) { 68 // Came from all apps prediction row -- make a copy 69 info = WorkspaceItemInfo(info) 70 } 71 return createShortcut(info, parent) 72 } 73 Favorites.ITEM_TYPE_FOLDER -> 74 return FolderIcon.inflateFolderAndIcon( 75 R.layout.folder_icon, 76 context, 77 parent, 78 item as FolderInfo 79 ) 80 Favorites.ITEM_TYPE_APP_PAIR -> 81 return AppPairIcon.inflateIcon( 82 R.layout.app_pair_icon, 83 context, 84 parent, 85 item as AppPairInfo, 86 BubbleTextView.DISPLAY_WORKSPACE 87 ) 88 Favorites.ITEM_TYPE_APPWIDGET, 89 Favorites.ITEM_TYPE_CUSTOM_APPWIDGET -> 90 return inflateAppWidget(item as LauncherAppWidgetInfo, writer) 91 else -> throw RuntimeException("Invalid Item Type") 92 } 93 } 94 95 /** 96 * Creates a view representing a shortcut inflated from the specified resource. 97 * 98 * @param parent The group the shortcut belongs to. This is not necessarily the group where the 99 * shortcut should be added. 100 * @param info The data structure describing the shortcut. 101 * @return A View inflated from layoutResId. 102 */ createShortcutnull103 private fun createShortcut(info: WorkspaceItemInfo, parent: ViewGroup): View { 104 val favorite = 105 LayoutInflater.from(parent.context).inflate(R.layout.app_icon, parent, false) 106 as BubbleTextView 107 favorite.applyFromWorkspaceItem(info) 108 favorite.setOnClickListener(clickListener) 109 favorite.onFocusChangeListener = focusListener 110 return favorite 111 } 112 inflateAppWidgetnull113 private fun inflateAppWidget(item: LauncherAppWidgetInfo, writer: ModelWriter): View? { 114 TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId) 115 try { 116 val (type, reason, _, isUpdate, widgetInfo) = widgetInflater.inflateAppWidget(item) 117 if (type == WidgetInflater.TYPE_DELETE) { 118 writer.deleteItemFromDatabase(item, reason) 119 return null 120 } 121 if (isUpdate) { 122 writer.updateItemInDatabase(item) 123 } 124 val view = 125 if (type == WidgetInflater.TYPE_PENDING || widgetInfo == null) 126 PendingAppWidgetHostView(context, widgetHolder, item, widgetInfo) 127 else widgetHolder.createView(item.appWidgetId, widgetInfo) 128 prepareAppWidget(view, item) 129 return view 130 } finally { 131 TraceHelper.INSTANCE.endSection() 132 } 133 } 134 prepareAppWidgetnull135 fun prepareAppWidget(hostView: AppWidgetHostView, item: LauncherAppWidgetInfo) { 136 hostView.tag = item 137 hostView.isFocusable = true 138 hostView.onFocusChangeListener = focusListener 139 } 140 } 141