Commit e6aed5dfc0a5daa06bc3767d0d316cb6b5fc90c5
- Diff rendering mode:
- inline
- side by side
|   | |||
| 124 | 124 | public String toString() { | |
| 125 | 125 | return title.toString(); | |
| 126 | 126 | } | |
| 127 | |||
| 128 | @Override | ||
| 129 | public void unbind() { | ||
| 130 | this.icon.setCallback(null); | ||
| 131 | } | ||
| 132 | 127 | } |
|   | |||
| 104 | 104 | } | |
| 105 | 105 | if (item instanceof UserFolderInfo) { | |
| 106 | 106 | final UserFolderInfo userFolderInfo = (UserFolderInfo)item; | |
| 107 | LauncherModel.deleteItemFromDatabase(mLauncher, userFolderInfo | ||
| 108 | ,LauncherSettings.Favorites.CONTAINER + "=" + userFolderInfo.id); | ||
| 107 | LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo); | ||
| 109 | 108 | model.removeUserFolder(userFolderInfo); | |
| 110 | 109 | } else if (item instanceof LauncherAppWidgetInfo) { | |
| 111 | 110 | final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item; | |
| 112 | mLauncher.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); | ||
| 111 | final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost(); | ||
| 112 | if (appWidgetHost != null) { | ||
| 113 | appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); | ||
| 114 | } | ||
| 113 | 115 | } | |
| 114 | 116 | LauncherModel.deleteItemFromDatabase(mLauncher, item); | |
| 115 | 117 | } |
|   | |||
| 31 | 31 | * The folder name. | |
| 32 | 32 | */ | |
| 33 | 33 | CharSequence title; | |
| 34 | |||
| 35 | @Override | ||
| 36 | public void unbind() { | ||
| 37 | // should we implement it? | ||
| 38 | } | ||
| 39 | 34 | } |
|   | |||
| 26 | 26 | /** | |
| 27 | 27 | * Represents an item in the launcher. | |
| 28 | 28 | */ | |
| 29 | abstract class ItemInfo { | ||
| 29 | class ItemInfo { | ||
| 30 | 30 | ||
| 31 | 31 | static final int NO_ID = -1; | |
| 32 | 32 | ||
| … | … | ||
| 129 | 129 | } | |
| 130 | 130 | } | |
| 131 | 131 | } | |
| 132 | |||
| 133 | abstract public void unbind(); | ||
| 134 | 132 | ||
| 135 | 133 | } |
|   | |||
| 89 | 89 | /** | |
| 90 | 90 | * Default launcher application. | |
| 91 | 91 | */ | |
| 92 | public final class Launcher extends LauncherInterface implements View.OnClickListener, OnLongClickListener { | ||
| 92 | public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener { | ||
| 93 | 93 | static final String LOG_TAG = "Launcher"; | |
| 94 | 94 | static final boolean LOGD = false; | |
| 95 | 95 | ||
| … | … | ||
| 210 | 210 | private DesktopBinder mBinder; | |
| 211 | 211 | ||
| 212 | 212 | @Override | |
| 213 | public void onCreate(Bundle savedInstanceState) { | ||
| 213 | protected void onCreate(Bundle savedInstanceState) { | ||
| 214 | 214 | super.onCreate(savedInstanceState); | |
| 215 | 215 | mInflater = getLayoutInflater(); | |
| 216 | 216 | ||
| … | … | ||
| 224 | 224 | android.os.Debug.startMethodTracing("/sdcard/launcher"); | |
| 225 | 225 | } | |
| 226 | 226 | ||
| 227 | mLocaleChanged = checkForLocaleChange(); | ||
| 227 | checkForLocaleChange(); | ||
| 228 | 228 | setWallpaperDimension(); | |
| 229 | 229 | ||
| 230 | 230 | setContentView(R.layout.launcher); | |
| … | … | ||
| 403 | 403 | } else if (requestCode == REQUEST_PICK_APPWIDGET && | |
| 404 | 404 | resultCode == RESULT_CANCELED && data != null) { | |
| 405 | 405 | // Clean up the appWidgetId if we canceled | |
| 406 | int appWidgetId = getWidgetIdExtra(data); | ||
| 406 | int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); | ||
| 407 | 407 | if (appWidgetId != -1) { | |
| 408 | deleteAppWidgetId(appWidgetId); | ||
| 408 | mAppWidgetHost.deleteAppWidgetId(appWidgetId); | ||
| 409 | 409 | } | |
| 410 | 410 | } | |
| 411 | 411 | } | |
| … | … | ||
| 784 | 784 | ShortcutIconResource iconResource = null; | |
| 785 | 785 | ||
| 786 | 786 | if (bitmap != null) { | |
| 787 | icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, this)); | ||
| 787 | icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, context)); | ||
| 788 | 788 | filtered = true; | |
| 789 | 789 | customIcon = true; | |
| 790 | 790 | } else { | |
| … | … | ||
| 804 | 804 | } | |
| 805 | 805 | ||
| 806 | 806 | if (icon == null) { | |
| 807 | icon = this.getPackageManager().getDefaultActivityIcon(); | ||
| 807 | icon = context.getPackageManager().getDefaultActivityIcon(); | ||
| 808 | 808 | } | |
| 809 | 809 | ||
| 810 | 810 | final ApplicationInfo info = new ApplicationInfo(); | |
| … | … | ||
| 922 | 922 | ||
| 923 | 923 | @Override | |
| 924 | 924 | public void onDestroy() { | |
| 925 | mDestroyed = true; | ||
| 926 | |||
| 925 | 927 | super.onDestroy(); | |
| 926 | 928 | ||
| 927 | 929 | try { | |
| … | … | ||
| 1111 | 1111 | ||
| 1112 | 1112 | void addAppWidget(Intent data) { | |
| 1113 | 1113 | // TODO: catch bad widget exception when sent | |
| 1114 | int appWidgetId = getWidgetIdExtra(data); | ||
| 1114 | int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); | ||
| 1115 | 1115 | ||
| 1116 | 1116 | String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET); | |
| 1117 | 1117 | if (SEARCH_WIDGET.equals(customWidget)) { | |
| 1118 | 1118 | // We don't need this any more, since this isn't a real app widget. | |
| 1119 | deleteAppWidgetId(appWidgetId); | ||
| 1119 | mAppWidgetHost.deleteAppWidgetId(appWidgetId); | ||
| 1120 | 1120 | // add the search widget | |
| 1121 | 1121 | addSearch(); | |
| 1122 | 1122 | } else { | |
| 1123 | AppWidgetProviderInfo appWidget = getAppWidgetInfo(appWidgetId); | ||
| 1123 | AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); | ||
| 1124 | 1124 | ||
| 1125 | 1125 | if (appWidget.configure != null) { | |
| 1126 | 1126 | // Launch over to configure widget, if needed | |
| … | … | ||
| 1226 | 1226 | } | |
| 1227 | 1227 | } | |
| 1228 | 1228 | ||
| 1229 | LiveFolderInfo addLiveFolder(Context context, Intent data, | ||
| 1229 | static LiveFolderInfo addLiveFolder(Context context, Intent data, | ||
| 1230 | 1230 | CellLayout.CellInfo cellInfo, boolean notify) { | |
| 1231 | 1231 | ||
| 1232 | 1232 | Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT); | |
| … | … | ||
| 1264 | 1264 | info.displayMode = data.getIntExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, | |
| 1265 | 1265 | LiveFolders.DISPLAY_MODE_GRID); | |
| 1266 | 1266 | ||
| 1267 | LauncherModel.addItemToDatabase(this, info, LauncherSettings.Favorites.CONTAINER_DESKTOP, | ||
| 1267 | LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP, | ||
| 1268 | 1268 | cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify); | |
| 1269 | 1269 | sModel.addFolder(info); | |
| 1270 | 1270 | ||
| … | … | ||
| 1340 | 1340 | * only a favorites observer to keep track of the favorites applications. | |
| 1341 | 1341 | */ | |
| 1342 | 1342 | private void registerContentObservers() { | |
| 1343 | ContentResolver resolver = getContentResolver(); | ||
| 1343 | ContentResolver resolver = getContentResolver(); | ||
| 1344 | 1344 | resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mObserver); | |
| 1345 | 1345 | } | |
| 1346 | 1346 |
|   | |||
| 50 | 50 | public String toString() { | |
| 51 | 51 | return Integer.toString(appWidgetId); | |
| 52 | 52 | } | |
| 53 | |||
| 54 | @Override | ||
| 55 | public void unbind() { | ||
| 56 | if(hostView != null) { | ||
| 57 | hostView = null; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | 53 | } |
|   | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008 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.launcher; | ||
| 18 | |||
| 19 | import android.app.Activity; | ||
| 20 | import android.content.ActivityNotFoundException; | ||
| 21 | import android.content.ContentResolver; | ||
| 22 | import android.content.Context; | ||
| 23 | import android.content.Intent; | ||
| 24 | import android.content.SharedPreferences; | ||
| 25 | import android.content.res.Configuration; | ||
| 26 | |||
| 27 | import android.widget.Toast; | ||
| 28 | |||
| 29 | import android.database.ContentObserver; | ||
| 30 | import android.appwidget.AppWidgetManager; | ||
| 31 | import android.appwidget.AppWidgetProviderInfo; | ||
| 32 | import android.appwidget.AppWidgetHost; | ||
| 33 | import android.appwidget.AppWidgetHostView; | ||
| 34 | |||
| 35 | import android.os.Bundle; | ||
| 36 | import android.os.Handler; | ||
| 37 | |||
| 38 | import android.util.Log; | ||
| 39 | /** | ||
| 40 | * Every Home Screen should extends this interface to cooperate with LauncherModel | ||
| 41 | * | ||
| 42 | * -Julian Chu, waklingice[at]0xlab.org | ||
| 43 | */ | ||
| 44 | |||
| 45 | public abstract class LauncherInterface extends Activity { | ||
| 46 | |||
| 47 | final static String LOG_TAG = "LauncherInterface"; | ||
| 48 | final static int APPWIDGET_HOST_ID = 1024; | ||
| 49 | |||
| 50 | private static final String PREFERENCES = "launcher"; | ||
| 51 | private static final String KEY_LOCALE = "locale"; | ||
| 52 | private static final String KEY_MCC = "mcc"; | ||
| 53 | private static final String KEY_MNC = "mnc"; | ||
| 54 | |||
| 55 | private AppWidgetHost mAppWidgetHost; | ||
| 56 | private ContentObserver mAppWidgetResetObserver; | ||
| 57 | private AppWidgetManager mAppWidgetManager; | ||
| 58 | |||
| 59 | abstract void callbackRefreshScreen(); | ||
| 60 | |||
| 61 | public void onCreate(Bundle savedInstanceState) { | ||
| 62 | super.onCreate(savedInstanceState); | ||
| 63 | |||
| 64 | mAppWidgetHost = new AppWidgetHost(this, APPWIDGET_HOST_ID); | ||
| 65 | mAppWidgetResetObserver = new AppWidgetResetObserver(); | ||
| 66 | mAppWidgetManager = AppWidgetManager.getInstance(this); | ||
| 67 | |||
| 68 | mAppWidgetHost.startListening(); | ||
| 69 | ContentResolver resolver = getContentResolver(); | ||
| 70 | resolver.registerContentObserver(LauncherProvider.CONTENT_APPWIDGET_RESET_URI, true, mAppWidgetResetObserver); | ||
| 71 | } | ||
| 72 | |||
| 73 | public void onDestroy() { | ||
| 74 | super.onDestroy(); | ||
| 75 | |||
| 76 | try { | ||
| 77 | mAppWidgetHost.stopListening(); | ||
| 78 | } catch (NullPointerException ex) { | ||
| 79 | Log.w(LOG_TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex); | ||
| 80 | } | ||
| 81 | getContentResolver().unregisterContentObserver(mAppWidgetResetObserver); | ||
| 82 | } | ||
| 83 | |||
| 84 | int getWidgetIdExtra(Intent data) { | ||
| 85 | return data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); | ||
| 86 | } | ||
| 87 | |||
| 88 | int allocateAppWidgetId() { | ||
| 89 | return mAppWidgetHost.allocateAppWidgetId(); | ||
| 90 | } | ||
| 91 | |||
| 92 | void deleteAppWidgetId(int appWidgetId) { | ||
| 93 | mAppWidgetHost.deleteAppWidgetId(appWidgetId); | ||
| 94 | } | ||
| 95 | |||
| 96 | AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) { | ||
| 97 | return mAppWidgetManager.getAppWidgetInfo(appWidgetId); | ||
| 98 | } | ||
| 99 | |||
| 100 | AppWidgetHostView createHostView(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) { | ||
| 101 | AppWidgetHostView hostview = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo); | ||
| 102 | hostview.setAppWidget(appWidgetId, appWidgetInfo); | ||
| 103 | return hostview; | ||
| 104 | } | ||
| 105 | |||
| 106 | void startActivitySafely(Intent intent) { | ||
| 107 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||
| 108 | try { | ||
| 109 | startActivity(intent); | ||
| 110 | } catch (ActivityNotFoundException e) { | ||
| 111 | Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); | ||
| 112 | } catch (SecurityException e) { | ||
| 113 | Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); | ||
| 114 | Log.e(LOG_TAG, "Launcher does not have the permission to launch " + intent + | ||
| 115 | ". Make sure to create a MAIN intent-filter for the corresponding activity " + | ||
| 116 | "or use the exported attribute for this activity.", e); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | protected boolean checkForLocaleChange() { | ||
| 121 | final SharedPreferences preferences = getSharedPreferences(PREFERENCES, MODE_PRIVATE); | ||
| 122 | final Configuration configuration = getResources().getConfiguration(); | ||
| 123 | |||
| 124 | final String previousLocale = preferences.getString(KEY_LOCALE, null); | ||
| 125 | final String locale = configuration.locale.toString(); | ||
| 126 | |||
| 127 | final int previousMcc = preferences.getInt(KEY_MCC, -1); | ||
| 128 | final int mcc = configuration.mcc; | ||
| 129 | |||
| 130 | final int previousMnc = preferences.getInt(KEY_MNC, -1); | ||
| 131 | final int mnc = configuration.mnc; | ||
| 132 | |||
| 133 | boolean mLocaleChanged = !locale.equals(previousLocale) || mcc != previousMcc || mnc != previousMnc; | ||
| 134 | |||
| 135 | if (mLocaleChanged) { | ||
| 136 | final SharedPreferences.Editor editor = preferences.edit(); | ||
| 137 | editor.putString(KEY_LOCALE, locale); | ||
| 138 | editor.putInt(KEY_MCC, mcc); | ||
| 139 | editor.putInt(KEY_MNC, mnc); | ||
| 140 | editor.commit(); | ||
| 141 | } | ||
| 142 | |||
| 143 | return mLocaleChanged; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | /** | ||
| 148 | * When reset, we handle by calling {@link AppWidgetHost#startListening()} | ||
| 149 | * to make sure our callbacks are set correctly. | ||
| 150 | */ | ||
| 151 | private void onAppWidgetReset() { | ||
| 152 | if (mAppWidgetHost != null) { | ||
| 153 | mAppWidgetHost.startListening(); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Receives notifications when the {@link AppWidgetHost} has been reset, | ||
| 159 | * usually only when the {@link LauncherProvider} database is first created. | ||
| 160 | */ | ||
| 161 | private class AppWidgetResetObserver extends ContentObserver { | ||
| 162 | public AppWidgetResetObserver() { | ||
| 163 | super(new Handler()); | ||
| 164 | } | ||
| 165 | |||
| 166 | @Override | ||
| 167 | public void onChange(boolean selfChange) { | ||
| 168 | onAppWidgetReset(); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } |
|   | |||
| 47 | 47 | * LauncherModel object held in a static. Also provide APIs for updating the database state | |
| 48 | 48 | * for the Launcher. | |
| 49 | 49 | */ | |
| 50 | public class LauncherModel extends LauncherModelInterface { | ||
| 50 | public class LauncherModel { | ||
| 51 | 51 | static final boolean DEBUG_LOADERS = true; | |
| 52 | 52 | static final String LOG_TAG = "HomeLoaders"; | |
| 53 | 53 | ||
| … | … | ||
| 106 | 106 | * @return true if the applications loader must be started | |
| 107 | 107 | * (see startApplicationsLoader()), false otherwise. | |
| 108 | 108 | */ | |
| 109 | synchronized boolean loadApplications(boolean isLaunching, LauncherInterface launcher, | ||
| 109 | synchronized boolean loadApplications(boolean isLaunching, Launcher launcher, | ||
| 110 | 110 | boolean localeChanged) { | |
| 111 | 111 | ||
| 112 | 112 | if (DEBUG_LOADERS) d(LOG_TAG, "load applications"); | |
| … | … | ||
| 170 | 170 | mApplicationsLoaderThread.start(); | |
| 171 | 171 | } | |
| 172 | 172 | ||
| 173 | synchronized void addPackage(LauncherInterface launcher, String packageName) { | ||
| 173 | synchronized void addPackage(Launcher launcher, String packageName) { | ||
| 174 | 174 | if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { | |
| 175 | 175 | startApplicationsLoaderLocked(launcher, false); | |
| 176 | 176 | return; | |
| … | … | ||
| 195 | 195 | } | |
| 196 | 196 | } | |
| 197 | 197 | ||
| 198 | synchronized void removePackage(LauncherInterface launcher, String packageName) { | ||
| 198 | synchronized void removePackage(Launcher launcher, String packageName) { | ||
| 199 | 199 | if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { | |
| 200 | 200 | dropApplicationCache(); // TODO: this could be optimized | |
| 201 | 201 | startApplicationsLoaderLocked(launcher, false); | |
| … | … | ||
| 231 | 231 | } | |
| 232 | 232 | } | |
| 233 | 233 | ||
| 234 | synchronized void updatePackage(LauncherInterface launcher, String packageName) { | ||
| 234 | synchronized void updatePackage(Launcher launcher, String packageName) { | ||
| 235 | 235 | if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { | |
| 236 | 236 | startApplicationsLoaderLocked(launcher, false); | |
| 237 | 237 | return; | |
| … | … | ||
| 275 | 275 | mAppInfoCache.put(componentName, applicationInfo); | |
| 276 | 276 | } | |
| 277 | 277 | ||
| 278 | synchronized void syncPackage(LauncherInterface launcher, String packageName) { | ||
| 278 | synchronized void syncPackage(Launcher launcher, String packageName) { | ||
| 279 | 279 | if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { | |
| 280 | 280 | startApplicationsLoaderLocked(launcher, false); | |
| 281 | 281 | return; | |
| … | … | ||
| 334 | 334 | } | |
| 335 | 335 | ||
| 336 | 336 | private boolean addEnabledAndUpdateActivities(List<ResolveInfo> matches, | |
| 337 | ApplicationsAdapter adapter, LauncherInterface launcher) { | ||
| 337 | ApplicationsAdapter adapter, Launcher launcher) { | ||
| 338 | 338 | ||
| 339 | 339 | final List<ApplicationInfo> toAdd = new ArrayList<ApplicationInfo>(); | |
| 340 | 340 | final int count = matches.size(); | |
| … | … | ||
| 481 | 481 | private static final AtomicInteger sWorkspaceLoaderCount = new AtomicInteger(1); | |
| 482 | 482 | ||
| 483 | 483 | private class ApplicationsLoader implements Runnable { | |
| 484 | private final WeakReference<PackageManager> manager_weakref; | ||
| 485 | private final WeakReference<LauncherInterface> interface_weakref; | ||
| 484 | private final WeakReference<Launcher> mLauncher; | ||
| 486 | 485 | ||
| 487 | 486 | private final Object stopLock = new Object(); | |
| 488 | 487 | private volatile boolean mStopped; | |
| … | … | ||
| 517 | 517 | final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); | |
| 518 | 518 | mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); | |
| 519 | 519 | ||
| 520 | final LauncherInterface launcher = interface_weakref.get(); | ||
| 521 | final PackageManager manager = manager_weakref.get(); | ||
| 522 | final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); | ||
| 520 | final Launcher launcher = mLauncher.get(); | ||
| 521 | final PackageManager manager = launcher.getPackageManager(); | ||
| 522 | final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); | ||
| 523 | 523 | ||
| 524 | 524 | if (apps != null && !mStopped) { | |
| 525 | 525 | final int count = apps.size(); | |
| … | … | ||
| 614 | 614 | * Loads all of the items on the desktop, in folders, or in the dock. | |
| 615 | 615 | * These can be apps, shortcuts or widgets | |
| 616 | 616 | */ | |
| 617 | void loadUserItems(boolean isLaunching, LauncherInterface launcher, boolean localeChanged, | ||
| 617 | void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged, | ||
| 618 | 618 | boolean loadApplications) { | |
| 619 | 619 | if (DEBUG_LOADERS) d(LOG_TAG, "loading user items"); | |
| 620 | 620 | ||
| … | … | ||
| 727 | 727 | private volatile boolean mStopped; | |
| 728 | 728 | private volatile boolean mRunning; | |
| 729 | 729 | ||
| 730 | private final WeakReference<LauncherInterface> launcher_weakref; | ||
| 730 | private final WeakReference<Launcher> mLauncher; | ||
| 731 | 731 | private final boolean mLocaleChanged; | |
| 732 | 732 | private final boolean mLoadApplications; | |
| 733 | 733 | private final boolean mIsLaunching; | |
| … | … | ||
| 916 | 916 | ||
| 917 | 917 | container = c.getInt(containerIndex); | |
| 918 | 918 | if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { | |
| 919 | e(LOG_TAG, "Widget found where container " | ||
| 919 | e(Launcher.LOG_TAG, "Widget found where container " | ||
| 920 | 920 | + "!= CONTAINER_DESKTOP ignoring!"); | |
| 921 | 921 | continue; | |
| 922 | 922 | } | |
| … | … | ||
| 942 | 942 | ||
| 943 | 943 | container = c.getInt(containerIndex); | |
| 944 | 944 | if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { | |
| 945 | e(LOG_TAG, "Widget found where container " | ||
| 945 | e(Launcher.LOG_TAG, "Widget found where container " | ||
| 946 | 946 | + "!= CONTAINER_DESKTOP -- ignoring!"); | |
| 947 | 947 | continue; | |
| 948 | 948 | } | |
| … | … | ||
| 952 | 952 | break; | |
| 953 | 953 | } | |
| 954 | 954 | } catch (Exception e) { | |
| 955 | w(LOG_TAG, "Desktop items loading interrupted:", e); | ||
| 955 | w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e); | ||
| 956 | 956 | } | |
| 957 | 957 | } | |
| 958 | 958 | } finally { | |
| … | … | ||
| 1002 | 1002 | } | |
| 1003 | 1003 | } | |
| 1004 | 1004 | ||
| 1005 | private static void loadLiveFolderIcon(LauncherInterface launcher, Cursor c, int iconTypeIndex, | ||
| 1005 | private static void loadLiveFolderIcon(Launcher launcher, Cursor c, int iconTypeIndex, | ||
| 1006 | 1006 | int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) { | |
| 1007 | 1007 | ||
| 1008 | 1008 | int iconType = c.getInt(iconTypeIndex); | |
| … | … | ||
| 1081 | 1081 | // Interrupt the applications loader before setting the adapter to null | |
| 1082 | 1082 | stopAndWaitForApplicationsLoader(); | |
| 1083 | 1083 | mApplicationsAdapter = null; | |
| 1084 | |||
| 1085 | /* FIXME Well, I know its stupid, but let it work first - Ju1ian*/ | ||
| 1086 | ArrayList<ItemInfo> list_apps = new ArrayList<ItemInfo>(mApplications.size()); | ||
| 1087 | ArrayList<ItemInfo> list_wigs = new ArrayList<ItemInfo>(mDesktopAppWidgets.size()); | ||
| 1088 | for (int i = 0; i < mApplications.size(); i++) { | ||
| 1089 | list_apps.add((ItemInfo)mApplications.get(i)); | ||
| 1090 | } | ||
| 1091 | for (int i = 0; i < mDesktopAppWidgets.size(); i++) { | ||
| 1092 | list_wigs.add((ItemInfo)mDesktopAppWidgets.get(i)); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | unbindItemInfo(mDesktopItems); | ||
| 1096 | unbindItemInfo(list_apps); | ||
| 1097 | unbindItemInfo(list_wigs); | ||
| 1084 | unbindAppDrawables(mApplications); | ||
| 1085 | unbindDrawables(mDesktopItems); | ||
| 1086 | unbindAppWidgetHostViews(mDesktopAppWidgets); | ||
| 1098 | 1087 | unbindCachedIconDrawables(); | |
| 1099 | 1088 | } | |
| 1100 | 1089 | ||
| … | … | ||
| 1091 | 1091 | * Remove the callback for the cached drawables or we leak the previous | |
| 1092 | 1092 | * Home screen on orientation change. | |
| 1093 | 1093 | */ | |
| 1094 | private void unbindItemInfo(ArrayList<ItemInfo> items) { | ||
| 1095 | if (items == null) { | ||
| 1096 | return; | ||
| 1097 | } | ||
| 1094 | private void unbindDrawables(ArrayList<ItemInfo> desktopItems) { | ||
| 1095 | if (desktopItems != null) { | ||
| 1096 | final int count = desktopItems.size(); | ||
| 1097 | for (int i = 0; i < count; i++) { | ||
| 1098 | ItemInfo item = desktopItems.get(i); | ||
| 1099 | switch (item.itemType) { | ||
| 1100 | case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: | ||
| 1101 | case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: | ||
| 1102 | ((ApplicationInfo)item).icon.setCallback(null); | ||
| 1103 | break; | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | } | ||
| 1098 | 1108 | ||
| 1099 | for (int i = 0; i < items.size(); i++) { | ||
| 1100 | items.get(i).unbind(); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1109 | /** | ||
| 1110 | * Remove the callback for the cached drawables or we leak the previous | ||
| 1111 | * Home screen on orientation change. | ||
| 1112 | */ | ||
| 1113 | private void unbindAppDrawables(ArrayList<ApplicationInfo> applications) { | ||
| 1114 | if (applications != null) { | ||
| 1115 | final int count = applications.size(); | ||
| 1116 | for (int i = 0; i < count; i++) { | ||
| 1117 | applications.get(i).icon.setCallback(null); | ||
| 1118 | } | ||
| 1119 | } | ||
| 1120 | } | ||
| 1103 | 1121 | ||
| 1104 | 1122 | /** | |
| 1123 | * Remove any {@link LauncherAppWidgetHostView} references in our widgets. | ||
| 1124 | */ | ||
| 1125 | private void unbindAppWidgetHostViews(ArrayList<LauncherAppWidgetInfo> appWidgets) { | ||
| 1126 | if (appWidgets != null) { | ||
| 1127 | final int count = appWidgets.size(); | ||
| 1128 | for (int i = 0; i < count; i++) { | ||
| 1129 | LauncherAppWidgetInfo launcherInfo = appWidgets.get(i); | ||
| 1130 | launcherInfo.hostView = null; | ||
| 1131 | } | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | /** | ||
| 1105 | 1136 | * Remove the callback for the cached drawables or we leak the previous | |
| 1106 | 1137 | * Home screen on orientation change. | |
| 1107 | 1138 | */ | |
| 1108 | 1139 | private void unbindCachedIconDrawables() { | |
| 1109 | 1140 | for (ApplicationInfo appInfo : mAppInfoCache.values()) { | |
| 1110 | appInfo.unbind(); | ||
| 1141 | appInfo.icon.setCallback(null); | ||
| 1111 | 1142 | } | |
| 1112 | 1143 | } | |
| 1113 | 1144 | ||
| … | … | ||
| 1323 | 1323 | * Returns true if the shortcuts already exists in the database. | |
| 1324 | 1324 | * we identify a shortcut by its title and intent. | |
| 1325 | 1325 | */ | |
| 1326 | static boolean shortcutExists(LauncherInterface launcher, String title, Intent intent) { | ||
| 1327 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 1326 | static boolean shortcutExists(Context context, String title, Intent intent) { | ||
| 1327 | final ContentResolver cr = context.getContentResolver(); | ||
| 1328 | 1328 | Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, | |
| 1329 | 1329 | new String[] { "title", "intent" }, "title=? and intent=?", | |
| 1330 | 1330 | new String[] { title, intent.toUri(0) }, null); | |
| … | … | ||
| 1337 | 1337 | return result; | |
| 1338 | 1338 | } | |
| 1339 | 1339 | ||
| 1340 | FolderInfo getFolderById(LauncherInterface launcher, long id) { | ||
| 1341 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 1340 | FolderInfo getFolderById(Context context, long id) { | ||
| 1341 | final ContentResolver cr = context.getContentResolver(); | ||
| 1342 | 1342 | Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null, | |
| 1343 | 1343 | "_id=? and (itemType=? or itemType=?)", | |
| 1344 | 1344 | new String[] { String.valueOf(id), |
|   | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008 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.launcher; | ||
| 18 | |||
| 19 | import android.content.ComponentName; | ||
| 20 | import android.content.ContentResolver; | ||
| 21 | import android.content.ContentValues; | ||
| 22 | import android.content.Intent; | ||
| 23 | import android.content.Context; | ||
| 24 | import android.content.pm.ActivityInfo; | ||
| 25 | import android.content.pm.PackageManager; | ||
| 26 | import android.content.pm.ResolveInfo; | ||
| 27 | import android.content.res.Resources; | ||
| 28 | import android.database.Cursor; | ||
| 29 | import android.graphics.Bitmap; | ||
| 30 | import android.graphics.BitmapFactory; | ||
| 31 | import android.graphics.drawable.Drawable; | ||
| 32 | import android.net.Uri; | ||
| 33 | import static android.util.Log.*; | ||
| 34 | import android.os.Process; | ||
| 35 | |||
| 36 | import java.util.ArrayList; | ||
| 37 | import java.util.HashMap; | ||
| 38 | import java.util.List; | ||
| 39 | import java.util.Comparator; | ||
| 40 | import java.lang.ref.WeakReference; | ||
| 41 | import java.text.Collator; | ||
| 42 | import java.net.URISyntaxException; | ||
| 43 | |||
| 44 | public abstract class LauncherModelInterface { | ||
| 45 | /** | ||
| 46 | * Add an item to the database in a specified container. Sets the container, screen, cellX and | ||
| 47 | * cellY fields of the item. Also assigns an ID to the item. | ||
| 48 | */ | ||
| 49 | static void addItemToDatabase(LauncherInterface launcher, ItemInfo item, long container, | ||
| 50 | int screen, int cellX, int cellY, boolean notify) { | ||
| 51 | item.container = container; | ||
| 52 | item.screen = screen; | ||
| 53 | item.cellX = cellX; | ||
| 54 | item.cellY = cellY; | ||
| 55 | |||
| 56 | final ContentValues values = new ContentValues(); | ||
| 57 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 58 | |||
| 59 | item.onAddToDatabase(values); | ||
| 60 | |||
| 61 | Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI : | ||
| 62 | LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values); | ||
| 63 | |||
| 64 | if (result != null) { | ||
| 65 | item.id = Integer.parseInt(result.getPathSegments().get(1)); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | /** | ||
| 69 | * Update an item to the database in a specified container. | ||
| 70 | */ | ||
| 71 | static void updateItemInDatabase(LauncherInterface launcher, ItemInfo item) { | ||
| 72 | final ContentValues values = new ContentValues(); | ||
| 73 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 74 | |||
| 75 | item.onAddToDatabase(values); | ||
| 76 | |||
| 77 | cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null); | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Removes the specified item from the database | ||
| 82 | * @param launcher | ||
| 83 | * @param item | ||
| 84 | */ | ||
| 85 | static void deleteItemFromDatabase(LauncherInterface launcher, ItemInfo item, String where) { | ||
| 86 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 87 | |||
| 88 | cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null); | ||
| 89 | if (where != null) { | ||
| 90 | cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), where, null); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | /** | ||
| 94 | * Removes the specified item from the database | ||
| 95 | * @param launcher | ||
| 96 | * @param item | ||
| 97 | */ | ||
| 98 | static void deleteItemFromDatabase(LauncherInterface launcher, ItemInfo item) { | ||
| 99 | deleteItemFromDatabase(launcher, item, null); | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * Adds an item to the DB if it was not created previously, or move it to a new | ||
| 104 | * <container, screen, cellX, cellY> | ||
| 105 | */ | ||
| 106 | static void addOrMoveItemInDatabase(LauncherInterface launcher, ItemInfo item, long container, | ||
| 107 | int screen, int cellX, int cellY) { | ||
| 108 | if (item.container == ItemInfo.NO_ID) { | ||
| 109 | // From all apps | ||
| 110 | addItemToDatabase(launcher, item, container, screen, cellX, cellY, false); | ||
| 111 | } else { | ||
| 112 | // From somewhere else | ||
| 113 | moveItemInDatabase(launcher, item, container, screen, cellX, cellY); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Move an item in the DB to a new <container, screen, cellX, cellY> | ||
| 119 | */ | ||
| 120 | static void moveItemInDatabase(LauncherInterface launcher, ItemInfo item, long container, int screen, | ||
| 121 | int cellX, int cellY) { | ||
| 122 | item.container = container; | ||
| 123 | item.screen = screen; | ||
| 124 | item.cellX = cellX; | ||
| 125 | item.cellY = cellY; | ||
| 126 | |||
| 127 | final ContentValues values = new ContentValues(); | ||
| 128 | final ContentResolver cr = launcher.getContentResolver(); | ||
| 129 | |||
| 130 | values.put(LauncherSettings.Favorites.CONTAINER, item.container); | ||
| 131 | values.put(LauncherSettings.Favorites.CELLX, item.cellX); | ||
| 132 | values.put(LauncherSettings.Favorites.CELLY, item.cellY); | ||
| 133 | values.put(LauncherSettings.Favorites.SCREEN, item.screen); | ||
| 134 | |||
| 135 | cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null); | ||
| 136 | } | ||
| 137 | |||
| 138 | } |
|   | |||
| 43 | 43 | OnClickListener { | |
| 44 | 44 | ||
| 45 | 45 | private static final Integer[] THUMB_IDS = { | |
| 46 | R.drawable.wallpaper_0xlab_small, | ||
| 47 | 46 | R.drawable.wallpaper_lake_small, | |
| 48 | 47 | R.drawable.wallpaper_sunset_small, | |
| 49 | 48 | R.drawable.wallpaper_beach_small, | |
| … | … | ||
| 60 | 60 | }; | |
| 61 | 61 | ||
| 62 | 62 | private static final Integer[] IMAGE_IDS = { | |
| 63 | R.drawable.wallpaper_0xlab, | ||
| 64 | 63 | R.drawable.wallpaper_lake, | |
| 65 | 64 | R.drawable.wallpaper_sunset, | |
| 66 | 65 | R.drawable.wallpaper_beach, |
|   | |||
| 33 | 33 | w.layoutResource = R.layout.widget_search; | |
| 34 | 34 | return w; | |
| 35 | 35 | } | |
| 36 | |||
| 37 | @Override | ||
| 38 | public void unbind() { | ||
| 39 | // should we implement it? | ||
| 40 | } | ||
| 41 | 36 | } |
|   | |||
| 251 | 251 | } | |
| 252 | 252 | ||
| 253 | 253 | /** | |
| 254 | * Set the Rect array to mask cells which cannot contain dragItem. | ||
| 255 | * | ||
| 256 | * In the end of this method, mOccupiedRects stores the rectangles. | ||
| 257 | * which tells if it can contain dragItem or not. | ||
| 258 | * @param dragItem the item be dragged by user | ||
| 259 | */ | ||
| 260 | void setOccupied(View dragItem) { | ||
| 261 | CellLayout current = ((CellLayout) getChildAt(mCurrentScreen)); | ||
| 262 | int count = getChildCount(); | ||
| 263 | int size = current.getCountX() * current.getCountY(); | ||
| 264 | |||
| 265 | /* Allocate necessary objects */ | ||
| 266 | mOccupiedCells = new boolean[count][size]; | ||
| 267 | mOccupiedRects = new Rect[count][size]; | ||
| 268 | for(int i=0; i<count ;i++) { | ||
| 269 | for(int j=0; j<size ;j++) { | ||
| 270 | mOccupiedRects[i][j] = new Rect(); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | /* get occupied cells from CellLayout */ | ||
| 275 | for(int i=0; i< count ; i++) { | ||
| 276 | CellLayout layout = ((CellLayout) getChildAt(i)); | ||
| 277 | mOccupiedCells[i] = layout.getOccupiedCells(); | ||
| 278 | } | ||
| 279 | |||
| 280 | Rect hit = new Rect(); | ||
| 281 | dragItem.getHitRect(hit); | ||
| 282 | /* For each screen of Workspace */ | ||
| 283 | for(int i=0; i< count ; i++) { | ||
| 284 | CellLayout layout = ((CellLayout) getChildAt(i)); | ||
| 285 | Rect[] occupiedRects = mOccupiedRects[i]; | ||
| 286 | int[] span = layout.rectToCell(hit.width(), hit.height()); | ||
| 287 | |||
| 288 | /* First, set all rect as occupied and map to 2-dimentional array */ | ||
| 289 | Rect[][] map = new Rect[layout.getCountX()][layout.getCountY()]; | ||
| 290 | for(int j=0; j<occupiedRects.length; j++) { | ||
| 291 | int x = j%layout.getCountX(); | ||
| 292 | int y = (int)(j/layout.getCountX()); | ||
| 293 | layout.cellToRect(x, y, 1, 1, occupiedRects[j]); | ||
| 294 | map[x][y] = occupiedRects[j]; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Find vacant cells which can contain dragItem */ | ||
| 298 | ArrayList<Rect> accept = new ArrayList<Rect>(); | ||
| 299 | for(int j=0; j<mOccupiedCells[i].length; j++) { | ||
| 300 | int x = j%layout.getCountX(); | ||
| 301 | int y = (int)(j/layout.getCountX()); | ||
| 302 | |||
| 303 | if(layout.acceptCellDrop(x, y, span[0], span[1], dragItem)) { | ||
| 304 | Rect r = new Rect(x, y, x+span[0], y+span[1]); | ||
| 305 | accept.add(r); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | /* Every cell which can contain dragItem should not have mask */ | ||
| 310 | for(Rect cell: accept) { | ||
| 311 | for(int row=cell.left; row<cell.right ;row++) { | ||
| 312 | for(int col=cell.top; col<cell.bottom ;col++) { | ||
| 313 | map[row][col].setEmpty(); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | /** | ||
| 322 | * Return the Rect array which is vacant or not of current screen. | ||
| 323 | */ | ||
| 324 | Rect[] getOccupiedRect() { | ||
| 325 | return mOccupiedRects[mCurrentScreen]; | ||
| 326 | } | ||
| 327 | |||
| 328 | /** | ||
| 329 | 254 | * Set the background's wallpaper. | |
| 330 | 255 | */ | |
| 331 | 256 | void loadWallpaper(Bitmap bitmap) { |

