summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornebkat <nebkat@teamhacksung.org>2012-12-25 15:33:18 +0000
committernebkat <nebkat@teamhacksung.org>2012-12-26 13:37:21 +0000
commit10a574501d4f4426ab5cec0a613b60d1d0baed44 (patch)
tree9f8718ecf66b46193d5eee04a947faf562318a73
parentb79406c0a85568dbc9150bbdb5339405b924f1fb (diff)
downloadpackages_apps_trebuchet-10a574501d4f4426ab5cec0a613b60d1d0baed44.zip
packages_apps_trebuchet-10a574501d4f4426ab5cec0a613b60d1d0baed44.tar.gz
packages_apps_trebuchet-10a574501d4f4426ab5cec0a613b60d1d0baed44.tar.bz2
Cleanup
Change-Id: Ied69f285305dbc3e1bf62676f23c47d6c6969e0a
-rw-r--r--res/layout/wallpaper_chooser.xml2
-rw-r--r--res/values-de/strings.xml2
-rw-r--r--res/values-fr/strings.xml4
-rw-r--r--res/values/attrs.xml20
-rw-r--r--res/values/config.xml4
-rw-r--r--res/values/strings.xml4
-rw-r--r--src/com/cyanogenmod/trebuchet/AllAppsList.java8
-rw-r--r--src/com/cyanogenmod/trebuchet/AppWidgetResizeFrame.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/AppsCustomizePagedView.java117
-rw-r--r--src/com/cyanogenmod/trebuchet/AppsCustomizeTabHost.java9
-rw-r--r--src/com/cyanogenmod/trebuchet/BubbleTextView.java1
-rw-r--r--src/com/cyanogenmod/trebuchet/ButtonDropTarget.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/CellLayout.java52
-rw-r--r--src/com/cyanogenmod/trebuchet/Cling.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/DeleteDropTarget.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/DragController.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/DragLayer.java12
-rw-r--r--src/com/cyanogenmod/trebuchet/FocusHelper.java10
-rw-r--r--src/com/cyanogenmod/trebuchet/FocusOnlyTabWidget.java4
-rw-r--r--src/com/cyanogenmod/trebuchet/Folder.java23
-rw-r--r--src/com/cyanogenmod/trebuchet/FolderIcon.java44
-rw-r--r--src/com/cyanogenmod/trebuchet/FolderInfo.java16
-rw-r--r--src/com/cyanogenmod/trebuchet/HandleView.java76
-rw-r--r--src/com/cyanogenmod/trebuchet/Hotseat.java8
-rw-r--r--src/com/cyanogenmod/trebuchet/InstallShortcutReceiver.java6
-rw-r--r--src/com/cyanogenmod/trebuchet/InterruptibleInOutAnimator.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/ItemInfo.java3
-rw-r--r--src/com/cyanogenmod/trebuchet/Launcher.java202
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java5
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherModel.java275
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherProvider.java20
-rw-r--r--src/com/cyanogenmod/trebuchet/PagedView.java26
-rw-r--r--src/com/cyanogenmod/trebuchet/ShortcutInfo.java3
-rw-r--r--src/com/cyanogenmod/trebuchet/SmoothPagedView.java188
-rw-r--r--src/com/cyanogenmod/trebuchet/StrokedTextView.java12
-rw-r--r--src/com/cyanogenmod/trebuchet/SymmetricalLinearTween.java118
-rw-r--r--src/com/cyanogenmod/trebuchet/TweenCallback.java24
-rw-r--r--src/com/cyanogenmod/trebuchet/UninstallShortcutReceiver.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/UserInitializeReceiver.java1
-rw-r--r--src/com/cyanogenmod/trebuchet/Utilities.java27
-rw-r--r--src/com/cyanogenmod/trebuchet/WallpaperChooserDialogFragment.java16
-rw-r--r--src/com/cyanogenmod/trebuchet/Workspace.java209
-rw-r--r--src/com/cyanogenmod/trebuchet/preference/DoubleNumberPickerPreference.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/preference/HiddenAppsActivity.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/preference/PreferencesProvider.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/widget/CustomAbsSpinner.java507
-rw-r--r--src/com/cyanogenmod/trebuchet/widget/CustomAdapterView.java1130
-rw-r--r--src/com/cyanogenmod/trebuchet/widget/EcoGallery.java1415
48 files changed, 3431 insertions, 1212 deletions
diff --git a/res/layout/wallpaper_chooser.xml b/res/layout/wallpaper_chooser.xml
index 4993076..62f22ee 100644
--- a/res/layout/wallpaper_chooser.xml
+++ b/res/layout/wallpaper_chooser.xml
@@ -29,7 +29,7 @@
android:layout_alignParentBottom="true"
android:background="@drawable/wallpaper_gallery_background">
- <Gallery android:id="@+id/gallery"
+ <com.cyanogenmod.trebuchet.widget.EcoGallery android:id="@+id/gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spacing="-4dp" />
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index aa45396..124c3a9 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -220,8 +220,6 @@
<string name="preferences_interface_drawer_indicator_enable_summary">Seitenindikator anzeigen</string>
<string name="preferences_interface_drawer_indicator_fade_title">Automatisch ausblenden</string>
<string name="preferences_interface_drawer_indicator_fade_summary">Indikator nach Seitenwechsel ausblenden</string>
- <string name="preferences_interface_homescreen_indicator_background_title">Dock-Abtrennung anzeigen</string>
- <string name="preferences_interface_homescreen_indicator_background_summary">Linie als Indikator-Hintergrund anzeigen</string>
<!-- Dock -->
<string name="preferences_interface_dock_title">Dock</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 241e1c2..fa7e1df 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -139,10 +139,6 @@
<string name="preferences_interface_homescreen_general_grid_summary">Définir le nombre de rangées et de colonnes sur l\'écran d\'accueil</string>
<string name="preferences_interface_homescreen_general_grid_rows_title">Rangées</string>
<string name="preferences_interface_homescreen_general_grid_columns_title">Colonnes</string>
- <string name="preferences_interface_homescreen_general_screen_padding_vertical_title">Marge verticale</string>
- <string name="preferences_interface_homescreen_general_screen_padding_vertical_summary">Espacement supplémentaire vertical sur l\'écran d\'accueil</string>
- <string name="preferences_interface_homescreen_general_screen_padding_horizontal_title">Marge horizontale</string>
- <string name="preferences_interface_homescreen_general_screen_padding_horizontal_summary">Espacement supplémentaire horizontal</string>
<string name="preferences_interface_homescreen_general_search_summary">Activer la barre de recherche persistante</string>
<string name="preferences_interface_homescreen_general_resize_any_widget_title">Redimensionner tous les widgets</string>
<string name="preferences_interface_homescreen_general_resize_any_widget_summary">Permet de redimensionner les widgets qui normalement n\'en sont pas capables</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 981897d..a8f0d21 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -130,13 +130,6 @@
<attr name="clingFocusedY" format="integer" />
</declare-styleable>
- <!-- HandleView specific attributes. These attributes are used to customize
- a HandleView view in XML files. -->
- <declare-styleable name="HandleView">
- <!-- Orientation of the handle. -->
- <attr name="direction" />
- </declare-styleable>
-
<!-- XML attributes used by default_workspace.xml -->
<declare-styleable name="Favorite">
<attr name="className" format="string" />
@@ -183,4 +176,17 @@
<attr name="pickerTitle1" format="string" />
<attr name="pickerTitle2" format="string" />
</declare-styleable>
+
+ <declare-styleable name="EcoGallery">
+ <attr name="gravity" format="integer" />
+ <attr name="animationDuration" format="integer" />
+ <attr name="unselectedAlpha" format="float" />
+ <attr name="spacing" format="dimension" />
+ </declare-styleable>
+ <attr name="ecoGalleryStyle" format="reference" />
+
+ <declare-styleable name="CustomAbsSpinner">
+ <attr name="entries" format="reference" />
+ </declare-styleable>
+ <attr name="customAbsSpinnerStyle" format="reference" />
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 91fec67..86d2924 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -35,10 +35,6 @@
AppsCustomize (y / x * 100%) -->
<integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
- <!-- Batch loading for loading in LauncherModel -->
- <integer name="config_allAppsBatchLoadDelay">0</integer>
- <integer name="config_allAppsBatchSize">0</integer>
-
<!-- Workspace -->
<!-- Whether or not the drop targets drop down as opposed to fade in -->
<bool name="config_useDropTargetDownTransition">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 849b964..37a97a0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -23,9 +23,9 @@
<!-- Application name -->
<string name="application_name" translatable="false">Trebuchet</string>
<!-- Application copyright -->
- <string name="application_copyright">Copyright \u00A9 CyanogenMod 2012</string>
+ <string name="application_copyright">Copyright \u00A9 CyanogenMod 2013</string>
<!-- Application version -->
- <string name="application_version">0.2</string>
+ <string name="application_version">1.0</string>
<!-- Accessibility-facing application name -->
<string name="home">Home</string>
<!-- Name for all applications running as this uid. -->
diff --git a/src/com/cyanogenmod/trebuchet/AllAppsList.java b/src/com/cyanogenmod/trebuchet/AllAppsList.java
index cc0e8cf..bab47c9 100644
--- a/src/com/cyanogenmod/trebuchet/AllAppsList.java
+++ b/src/com/cyanogenmod/trebuchet/AllAppsList.java
@@ -135,9 +135,7 @@ class AllAppsList {
// Find enabled activities and add them to the adapter
// Also updates existing activities with new labels/icons
- int count = matches.size();
- for (int i = 0; i < count; i++) {
- final ResolveInfo info = matches.get(i);
+ for (final ResolveInfo info : matches) {
ApplicationInfo applicationInfo = findApplicationInfoLocked(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
@@ -195,9 +193,7 @@ class AllAppsList {
* Returns whether <em>apps</em> contains <em>component</em>.
*/
private static boolean findActivity(ArrayList<ApplicationInfo> apps, ComponentName component) {
- final int N = apps.size();
- for (int i=0; i<N; i++) {
- final ApplicationInfo info = apps.get(i);
+ for (final ApplicationInfo info : apps) {
if (info.componentName.equals(component)) {
return true;
}
diff --git a/src/com/cyanogenmod/trebuchet/AppWidgetResizeFrame.java b/src/com/cyanogenmod/trebuchet/AppWidgetResizeFrame.java
index 39b5356..0493f76 100644
--- a/src/com/cyanogenmod/trebuchet/AppWidgetResizeFrame.java
+++ b/src/com/cyanogenmod/trebuchet/AppWidgetResizeFrame.java
@@ -13,7 +13,6 @@ import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
public class AppWidgetResizeFrame extends FrameLayout {
@@ -67,11 +66,6 @@ public class AppWidgetResizeFrame extends FrameLayout {
private static Rect mTmpRect = new Rect();
- public static final int LEFT = 0;
- public static final int TOP = 1;
- public static final int RIGHT = 2;
- public static final int BOTTOM = 3;
-
private Launcher mLauncher;
public AppWidgetResizeFrame(Context context,
diff --git a/src/com/cyanogenmod/trebuchet/AppsCustomizePagedView.java b/src/com/cyanogenmod/trebuchet/AppsCustomizePagedView.java
index e4bb84a..3da7f8e 100644
--- a/src/com/cyanogenmod/trebuchet/AppsCustomizePagedView.java
+++ b/src/com/cyanogenmod/trebuchet/AppsCustomizePagedView.java
@@ -51,9 +51,7 @@ import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
@@ -61,7 +59,6 @@ import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.Toast;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.DropTarget.DragObject;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
@@ -86,16 +83,6 @@ class AsyncTaskPageData {
LoadWidgetPreviewData
}
- AsyncTaskPageData(int p, ArrayList<Object> l, ArrayList<Bitmap> si, AsyncTaskCallback bgR,
- AsyncTaskCallback postR) {
- page = p;
- items = l;
- sourceImages = si;
- generatedImages = new ArrayList<Bitmap>();
- maxImageWidth = maxImageHeight = -1;
- doInBackgroundCallback = bgR;
- postExecuteCallback = postR;
- }
AsyncTaskPageData(int p, ArrayList<Object> l, int cw, int ch, AsyncTaskCallback bgR,
AsyncTaskCallback postR) {
page = p;
@@ -269,7 +256,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Save and Restore
private int mSaveInstanceStateItemIndex = -1;
private PagedViewIcon mPressedIcon;
- private int mRestorePage = -1;
// Content
private ContentType mContentType;
@@ -293,18 +279,15 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private int mContentWidth;
private int mAppIconSize;
private int mMaxAppCellCountX, mMaxAppCellCountY;
- private int mMaxWidgetSpan, mMinWidgetSpan;
private int mWidgetCountX, mWidgetCountY;
private int mWidgetWidthGap, mWidgetHeightGap;
- private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
+ private static final float WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE = 0.25f;
private PagedViewCellLayout mWidgetSpacingLayout;
private int mNumAppsPages = 0;
private int mNumWidgetPages = 0;
// Relating to the scroll and overscroll effects
Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
- private static float CAMERA_DISTANCE = 6500;
- private static final float TRANSITION_SCALE_FACTOR = 0.74f;
private static final float TRANSITION_PIVOT = 0.65f;
private static final float TRANSITION_MAX_ROTATION = 22;
private static final float TRANSITION_SCREEN_ROTATION = 12.5f;
@@ -432,11 +415,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mClingFocusedY = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedY, 0);
a.recycle();
mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
-
- // The max widget span is the length N, such that NxN is the largest bounds that the widget
- // preview can be before applying the widget scaling
- mMinWidgetSpan = 1;
- mMaxWidgetSpan = 3;
}
@Override
@@ -586,7 +564,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mWidgetSpacingLayout.measure(widthSpec, heightSpec);
mContentWidth = mWidgetSpacingLayout.getContentWidth();
- AppsCustomizeTabHost host = (AppsCustomizeTabHost) getTabHost();
+ AppsCustomizeTabHost host = getTabHost();
final boolean hostIsTransitioning = host.isTransitioning();
// Restore the page
@@ -634,7 +612,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (!isDataReady()) {
- boolean isReady = false;
+ boolean isReady;
if (mContentType == AppsCustomizePagedView.ContentType.Widgets || mJoinWidgetsApps) {
isReady = (!mApps.isEmpty() && !mWidgets.isEmpty());
} else {
@@ -747,7 +725,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mLauncher.getWorkspace().beginDragShared(v, this);
}
- Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
+ Bundle getDefaultOptionsForWidget(PendingAddWidgetInfo info) {
Bundle options = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, mTmpRect);
@@ -773,7 +751,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private void preloadWidget(final PendingAddWidgetInfo info) {
final AppWidgetProviderInfo pInfo = info.info;
- final Bundle options = getDefaultOptionsForWidget(mLauncher, info);
+ final Bundle options = getDefaultOptionsForWidget(info);
if (pInfo.configure != null) {
info.bindOptions = options;
@@ -814,7 +792,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mWidgetCleanupState = WIDGET_INFLATED;
hostView.setVisibility(INVISIBLE);
int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info.spanX,
- info.spanY, info, false);
+ info.spanY, false);
// We want the first widget layout to be the correct size. This will be important
// for width size reporting to the AppWidgetManager.
@@ -912,7 +890,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int spanX = createItemInfo.spanX;
int spanY = createItemInfo.spanY;
int[] size = mLauncher.getWorkspace().estimateItemSize(spanX, spanY,
- createWidgetInfo, true);
+ true);
FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
float minScale = 1.25f;
@@ -931,7 +909,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
(float) previewDrawable.getIntrinsicHeight()),
Matrix.ScaleToFit.START);
m.getValues(mv);
- scale = (float) mv[0];
+ scale = mv[0];
} else {
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
@@ -1117,7 +1095,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Clean up all the async tasks
Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+ AppsCustomizeAsyncTask task = iter.next();
task.cancel(false);
iter.remove();
mDirtyPageContent.set(task.page, true);
@@ -1151,9 +1129,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
updateCurrentTab(whichPage);
// Update the thread priorities given the direction lookahead
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+ for (AppsCustomizeAsyncTask task : mRunningTasks) {
int pageIndex = task.page;
if ((mNextPage > mCurrentPage && pageIndex >= mCurrentPage) ||
(mNextPage < mCurrentPage && pageIndex <= mCurrentPage)) {
@@ -1225,7 +1201,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
addView(layout);
}
}
- public void syncAppsPageItems(int page, boolean immediate) {
+ public void syncAppsPageItems(int page) {
// ensure that we have the right number of items on the pages
int numCells = mCellCountX * mCellCountY;
int startIndex = page * numCells;
@@ -1233,8 +1209,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
PagedViewCellLayout layout = (PagedViewCellLayout) getPageAt(page);
layout.removeAllViewsOnPage();
- ArrayList<Object> items = new ArrayList<Object>();
- ArrayList<Bitmap> images = new ArrayList<Bitmap>();
for (int i = startIndex; i < endIndex; ++i) {
ApplicationInfo info = mFilteredApps.get(i);
PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
@@ -1248,10 +1222,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int index = i - startIndex;
int x = index % mCellCountX;
int y = index / mCellCountX;
- layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
-
- items.add(info);
- images.add(info.iconBitmap);
+ layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x, y, 1, 1));
}
layout.createHardwareLayers();
@@ -1273,7 +1244,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
int minPageDiff = Integer.MAX_VALUE;
while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+ AppsCustomizeAsyncTask task = iter.next();
minPageDiff = Math.abs(task.page - toPage);
}
@@ -1303,12 +1274,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
* Creates and executes a new AsyncTask to load a page of widget previews.
*/
private void prepareLoadWidgetPreviewsTask(int page, ArrayList<Object> widgets,
- int cellWidth, int cellHeight, int cellCountX) {
+ int cellWidth, int cellHeight) {
// Prune all tasks that are no longer needed
Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+ AppsCustomizeAsyncTask task = iter.next();
int taskPage = task.page;
if (taskPage < getAssociatedLowerPageBound(mCurrentPage) ||
taskPage > getAssociatedUpperPageBound(mCurrentPage)) {
@@ -1328,7 +1299,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
try {
try {
Thread.sleep(sleepMs);
- } catch (Exception e) {}
+ } catch (Exception e) {
+ // Ignore
+ }
loadWidgetPreviewsInBackground(task, data);
} finally {
if (task.isCancelled()) {
@@ -1501,7 +1474,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
c.setBitmap(null);
// Draw the icon in the top left corner
- int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
+ int minOffset = (int) (mAppIconSize * WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE);
int smallestSide = Math.min(bitmapWidth, bitmapHeight);
float iconScale = Math.min((float) smallestSide
/ (mAppIconSize + 2 * minOffset), 1f);
@@ -1520,6 +1493,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
(int) (mAppIconSize * iconScale));
}
} catch (Resources.NotFoundException e) {
+ // Ignore
}
}
@@ -1597,7 +1571,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
layout.setColumnCount(layout.getCellCountX());
for (int i = 0; i < items.size(); ++i) {
Object rawInfo = items.get(i);
- PendingAddItemInfo createItemInfo = null;
+ PendingAddItemInfo createItemInfo;
PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
R.layout.apps_customize_widget, layout, false);
if (rawInfo instanceof AppWidgetProviderInfo) {
@@ -1677,7 +1651,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
} else {
prepareLoadWidgetPreviewsTask(page, items,
- maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
+ maxPreviewWidth, maxPreviewHeight);
}
}
}
@@ -1695,8 +1669,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Load each of the widget/shortcut previews
ArrayList<Object> items = data.items;
ArrayList<Bitmap> images = data.generatedImages;
- int count = items.size();
- for (int i = 0; i < count; ++i) {
+ for (Object item : items) {
if (task != null) {
// Ensure we haven't been cancelled yet
if (task.isCancelled()) break;
@@ -1705,9 +1678,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
task.syncThreadPriority();
}
- Object rawInfo = items.get(i);
- if (rawInfo instanceof AppWidgetProviderInfo) {
- AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
+ if (item instanceof AppWidgetProviderInfo) {
+ AppWidgetProviderInfo info = (AppWidgetProviderInfo) item;
int[] cellSpans = Launcher.getSpanForWidget(mLauncher, info);
int maxWidth = Math.min(data.maxImageWidth,
@@ -1717,12 +1689,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
Bitmap b = getWidgetPreview(info.provider, info.previewImage, info.icon,
cellSpans[0], cellSpans[1], maxWidth, maxHeight);
images.add(b);
- } else if (rawInfo instanceof ResolveInfo) {
+ } else if (item instanceof ResolveInfo) {
// Fill in the shortcuts information
- ResolveInfo info = (ResolveInfo) rawInfo;
+ ResolveInfo info = (ResolveInfo) item;
images.add(getShortcutPreview(info, data.maxImageWidth, data.maxImageHeight));
- } else if (rawInfo instanceof LauncherActionInfo) {
- LauncherActionInfo info = (LauncherActionInfo) rawInfo;
+ } else if (item instanceof LauncherActionInfo) {
+ LauncherActionInfo info = (LauncherActionInfo) item;
images.add(getShortcutPreview(info));
}
}
@@ -1751,9 +1723,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
invalidate();
// Update all thread priorities
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+ for (AppsCustomizeAsyncTask task : mRunningTasks) {
int pageIndex = task.page;
task.setThreadPriority(getThreadPriorityForPage(pageIndex));
}
@@ -1798,14 +1768,14 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
public void syncPageItems(int page, boolean immediate) {
if (mJoinWidgetsApps) {
if (page < mNumAppsPages) {
- syncAppsPageItems(page, immediate);
+ syncAppsPageItems(page);
} else {
syncWidgetPageItems(page, immediate);
}
} else {
switch (mContentType) {
case Applications:
- syncAppsPageItems(page, immediate);
+ syncAppsPageItems(page);
break;
case Widgets:
syncWidgetPageItems(page, immediate);
@@ -2187,9 +2157,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
if (v != null) {
float scrollProgress = getScrollProgress(screenScroll, v, index);
float rotation = -TRANSITION_MAX_ROTATION * scrollProgress;
- v.setCameraDistance(mDensity * mCameraDistance);
if (!mOverscrollTransformsDirty) {
mOverscrollTransformsDirty = true;
+ v.setCameraDistance(mDensity * mCameraDistance);
if (!mVertical) {
v.setPivotX(v.getMeasuredWidth() * (index == 0 ? TRANSITION_PIVOT : 1 - TRANSITION_PIVOT));
v.setPivotY(v.getMeasuredHeight() * 0.5f);
@@ -2238,16 +2208,17 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
if (!mVertical) {
if (mScrollingIndicatorPosition == SCROLLING_INDICATOR_BOTTOM) {
return R.id.paged_view_indicator_bottom;
- } else {
+ } else if (mScrollingIndicatorPosition == SCROLLING_INDICATOR_TOP) {
return R.id.paged_view_indicator_top;
}
} else {
if (mScrollingIndicatorPosition == SCROLLING_INDICATOR_BOTTOM) {
return R.id.paged_view_indicator_right;
- } else {
+ } else if (mScrollingIndicatorPosition == SCROLLING_INDICATOR_TOP) {
return R.id.paged_view_indicator_left;
}
}
+ return -1;
}
@Override
@@ -2332,9 +2303,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// We add it in place, in alphabetical order
- int count = list.size();
- for (int i = 0; i < count; ++i) {
- ApplicationInfo info = list.get(i);
+ for (ApplicationInfo info : list) {
int index = Collections.binarySearch(mApps, info, LauncherModel.getAppNameComparator());
if (index < 0) {
mApps.add(-(index + 1), info);
@@ -2370,9 +2339,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// loop through all the apps and remove apps that have the same component
- int length = list.size();
- for (int i = 0; i < length; ++i) {
- ApplicationInfo info = list.get(i);
+ for (ApplicationInfo info : list) {
int removeIndex = findAppByComponent(mApps, info);
if (removeIndex > -1) {
mApps.remove(removeIndex);
@@ -2518,15 +2485,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
protected int getAssociatedLowerPageBound(int page) {
final int count = getChildCount();
int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
- int windowMinIndex = Math.max(Math.min(page - sLookBehindPageCount, count - windowSize), 0);
- return windowMinIndex;
+ return Math.max(Math.min(page - sLookBehindPageCount, count - windowSize), 0);
}
protected int getAssociatedUpperPageBound(int page) {
final int count = getChildCount();
int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
- int windowMaxIndex = Math.min(Math.max(page + sLookAheadPageCount, windowSize - 1),
+ return Math.min(Math.max(page + sLookAheadPageCount, windowSize - 1),
count - 1);
- return windowMaxIndex;
}
@Override
@@ -2535,7 +2500,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int stringId = R.string.default_scroll_format;
if (mJoinWidgetsApps) {
- int count = 0;
+ int count;
if (page < mNumAppsPages) {
stringId = R.string.apps_customize_apps_scroll_format;
diff --git a/src/com/cyanogenmod/trebuchet/AppsCustomizeTabHost.java b/src/com/cyanogenmod/trebuchet/AppsCustomizeTabHost.java
index 5bffe76..af762ea 100644
--- a/src/com/cyanogenmod/trebuchet/AppsCustomizeTabHost.java
+++ b/src/com/cyanogenmod/trebuchet/AppsCustomizeTabHost.java
@@ -179,11 +179,8 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona
public boolean onInterceptTouchEvent(MotionEvent ev) {
// If we are mid transitioning to the workspace, then intercept touch events here so we
// can ignore them, otherwise we just let all apps handle the touch events.
- if (mInTransition && mTransitioningToWorkspace) {
- return true;
- }
- return super.onInterceptTouchEvent(ev);
- };
+ return mInTransition && mTransitioningToWorkspace || super.onInterceptTouchEvent(ev);
+ }
@Override
public boolean onTouchEvent(MotionEvent event) {
@@ -271,7 +268,7 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona
mAnimationBuffer.setVisibility(View.VISIBLE);
LayoutParams p = new FrameLayout.LayoutParams(child.getMeasuredWidth(),
child.getMeasuredHeight());
- p.setMargins((int) child.getLeft(), (int) child.getTop(), 0, 0);
+ p.setMargins(child.getLeft(), child.getTop(), 0, 0);
mAnimationBuffer.addView(child, p);
// Toggle the new content
diff --git a/src/com/cyanogenmod/trebuchet/BubbleTextView.java b/src/com/cyanogenmod/trebuchet/BubbleTextView.java
index 4c94bc9..8a48b16 100644
--- a/src/com/cyanogenmod/trebuchet/BubbleTextView.java
+++ b/src/com/cyanogenmod/trebuchet/BubbleTextView.java
@@ -34,7 +34,6 @@ import android.widget.TextView;
* too aggressive.
*/
public class BubbleTextView extends TextView implements ShortcutInfo.ShortcutListener {
- static final float CORNER_RADIUS = 4.0f;
static final float SHADOW_LARGE_RADIUS = 4.0f;
static final float SHADOW_SMALL_RADIUS = 1.75f;
static final float SHADOW_Y_OFFSET = 2.0f;
diff --git a/src/com/cyanogenmod/trebuchet/ButtonDropTarget.java b/src/com/cyanogenmod/trebuchet/ButtonDropTarget.java
index 8f819ea..9317d1d 100644
--- a/src/com/cyanogenmod/trebuchet/ButtonDropTarget.java
+++ b/src/com/cyanogenmod/trebuchet/ButtonDropTarget.java
@@ -71,9 +71,9 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro
protected Drawable getCurrentDrawable() {
Drawable[] drawables = getCompoundDrawables();
- for (int i = 0; i < drawables.length; ++i) {
- if (drawables[i] != null) {
- return drawables[i];
+ for (Drawable drawable : drawables) {
+ if (drawable != null) {
+ return drawable;
}
}
return null;
diff --git a/src/com/cyanogenmod/trebuchet/CellLayout.java b/src/com/cyanogenmod/trebuchet/CellLayout.java
index b70a34d..0521ef7 100644
--- a/src/com/cyanogenmod/trebuchet/CellLayout.java
+++ b/src/com/cyanogenmod/trebuchet/CellLayout.java
@@ -19,7 +19,6 @@ package com.cyanogenmod.trebuchet;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -49,7 +48,6 @@ import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LayoutAnimationController;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.FolderIcon.FolderRingAnimator;
import java.util.ArrayList;
@@ -362,7 +360,7 @@ public class CellLayout extends ViewGroup {
mOverScrollForegroundDrawable = mOverScrollRight;
}
- mForegroundAlpha = (int) Math.round((r * 255));
+ mForegroundAlpha = Math.round((r * 255));
mOverScrollForegroundDrawable.setAlpha(mForegroundAlpha);
invalidate();
}
@@ -495,14 +493,12 @@ public class CellLayout extends ViewGroup {
int previewOffset = FolderRingAnimator.sPreviewSize;
// The folder outer / inner ring image(s)
- for (int i = 0; i < mFolderOuterRings.size(); i++) {
- FolderRingAnimator fra = mFolderOuterRings.get(i);
-
+ for (FolderRingAnimator ringAnimator : mFolderOuterRings) {
// Draw outer ring
Drawable d = FolderRingAnimator.sSharedOuterRingDrawable;
- int width = (int) fra.getOuterRingSize();
+ int width = (int) ringAnimator.getOuterRingSize();
int height = width;
- cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+ cellToPoint(ringAnimator.mCellX, ringAnimator.mCellY, mTempLocation);
int centerX = mTempLocation[0] + mCellWidth / 2;
int centerY = mTempLocation[1] + previewOffset / 2;
@@ -515,9 +511,9 @@ public class CellLayout extends ViewGroup {
// Draw inner ring
d = FolderRingAnimator.sSharedInnerRingDrawable;
- width = (int) fra.getInnerRingSize();
+ width = (int) ringAnimator.getInnerRingSize();
height = width;
- cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+ cellToPoint(ringAnimator.mCellX, ringAnimator.mCellY, mTempLocation);
centerX = mTempLocation[0] + mCellWidth / 2;
centerY = mTempLocation[1] + previewOffset / 2;
@@ -897,9 +893,8 @@ public class CellLayout extends ViewGroup {
public float getDistanceFromCell(float x, float y, int[] cell) {
cellToCenterPoint(cell[0], cell[1], mTmpPoint);
- float distance = (float) Math.sqrt( Math.pow(x - mTmpPoint[0], 2) +
+ return (float) Math.sqrt( Math.pow(x - mTmpPoint[0], 2) +
Math.pow(y - mTmpPoint[1], 2));
- return distance;
}
void setCellGaps(int widthGap, int heightGap) {
@@ -1155,7 +1150,7 @@ public class CellLayout extends ViewGroup {
va.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- float r = ((Float) animation.getAnimatedValue()).floatValue();
+ float r = (Float) animation.getAnimatedValue();
lp.x = (int) ((1 - r) * oldX + r * newX);
lp.y = (int) ((1 - r) * oldY + r * newY);
child.requestLayout();
@@ -1456,9 +1451,6 @@ public class CellLayout extends ViewGroup {
hitMaxY |= ySize >= spanY;
incX = !incX;
}
- incX = true;
- hitMaxX = xSize >= spanX;
- hitMaxY = ySize >= spanY;
}
final int[] cellXY = mTmpXY;
cellToCenterPoint(x, y, cellXY);
@@ -1711,9 +1703,9 @@ public class CellLayout extends ViewGroup {
}
private void completeSetOfViewsToMove(ArrayList<View> views, Rect boundingRect, int[] direction,
- boolean[][] occupied, View dragView, ItemConfiguration currentState) {
+ View dragView, ItemConfiguration currentState) {
Rect r0 = new Rect(boundingRect);
- int minRuns = 0;
+ int minRuns;
// The first thing we do is to reduce the bounding rect to first or last row or column,
// depending on the direction. Then, we add any necessary views that are already contained
@@ -1761,7 +1753,7 @@ public class CellLayout extends ViewGroup {
@SuppressWarnings("unchecked")
ArrayList<View> dup = (ArrayList<View>) views.clone();
if (push) {
- completeSetOfViewsToMove(dup, boundingRect, direction, mTmpOccupied, dragView,
+ completeSetOfViewsToMove(dup, boundingRect, direction, dragView,
currentState);
}
@@ -1984,9 +1976,7 @@ public class CellLayout extends ViewGroup {
private void copyOccupiedArray(boolean[][] occupied) {
for (int i = 0; i < mCountX; i++) {
- for (int j = 0; j < mCountY; j++) {
- occupied[i][j] = mOccupied[i][j];
- }
+ System.arraycopy(mOccupied[i], 0, occupied[i], 0, mCountY);
}
}
@@ -2003,10 +1993,9 @@ public class CellLayout extends ViewGroup {
int result[] = new int[2];
result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
- boolean success = false;
// First we try the exact nearest position of the item being dragged,
// we will then want to try to move this around to other neighbouring positions
- success = rearrangementExists(result[0], result[1], spanX, spanY, direction, dragView,
+ boolean success = rearrangementExists(result[0], result[1], spanX, spanY, direction, dragView,
solution);
if (!success) {
@@ -2181,7 +2170,7 @@ public class CellLayout extends ViewGroup {
va.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- float r = ((Float) animation.getAnimatedValue()).floatValue();
+ float r = (Float) animation.getAnimatedValue();
float x = r * finalDeltaX + (1 - r) * initDeltaX;
float y = r * finalDeltaY + (1 - r) * initDeltaY;
child.setTranslationX(x);
@@ -2237,9 +2226,7 @@ public class CellLayout extends ViewGroup {
private void commitTempPlacement() {
for (int i = 0; i < mCountX; i++) {
- for (int j = 0; j < mCountY; j++) {
- mOccupied[i][j] = mTmpOccupied[i][j];
- }
+ System.arraycopy(mTmpOccupied[i], 0, mOccupied[i], 0, mCountY);
}
int childCount = mShortcutsAndWidgets.getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -2271,7 +2258,7 @@ public class CellLayout extends ViewGroup {
}
ItemConfiguration findConfigurationNoShuffle(int pixelX, int pixelY, int minSpanX, int minSpanY,
- int spanX, int spanY, View dragView, ItemConfiguration solution) {
+ int spanX, int spanY, ItemConfiguration solution) {
int[] result = new int[2];
int[] resultSpan = new int[2];
findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null, result,
@@ -2451,7 +2438,7 @@ public class CellLayout extends ViewGroup {
// We attempt the approach which doesn't shuffle views at all
ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
- minSpanY, spanX, spanY, dragView, new ItemConfiguration());
+ minSpanY, spanX, spanY, new ItemConfiguration());
ItemConfiguration finalSolution = null;
if (swapSolution.isSolution && swapSolution.area() >= noShuffleSolution.area()) {
@@ -2699,7 +2686,6 @@ public class CellLayout extends ViewGroup {
// intersecting
intersectX = -1;
intersectY = -1;
- continue;
}
}
@@ -3064,8 +3050,8 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
leftMargin - rightMargin;
height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
topMargin - bottomMargin;
- x = (int) (myCellX * (cellWidth + widthGap) + leftMargin);
- y = (int) (myCellY * (cellHeight + heightGap) + topMargin);
+ x = myCellX * (cellWidth + widthGap) + leftMargin;
+ y = myCellY * (cellHeight + heightGap) + topMargin;
}
}
diff --git a/src/com/cyanogenmod/trebuchet/Cling.java b/src/com/cyanogenmod/trebuchet/Cling.java
index 00a4464..510121b 100644
--- a/src/com/cyanogenmod/trebuchet/Cling.java
+++ b/src/com/cyanogenmod/trebuchet/Cling.java
@@ -210,7 +210,7 @@ public class Cling extends FrameLayout {
}
}
return true;
- };
+ }
@Override
protected void dispatchDraw(Canvas canvas) {
@@ -283,10 +283,10 @@ public class Cling extends FrameLayout {
canvas.drawBitmap(b, 0, 0, null);
c.setBitmap(null);
- b = null;
+ b.recycle();
}
// Draw the rest of the cling
super.dispatchDraw(canvas);
- };
+ }
}
diff --git a/src/com/cyanogenmod/trebuchet/DeleteDropTarget.java b/src/com/cyanogenmod/trebuchet/DeleteDropTarget.java
index 2cc872a..55381d4 100644
--- a/src/com/cyanogenmod/trebuchet/DeleteDropTarget.java
+++ b/src/com/cyanogenmod/trebuchet/DeleteDropTarget.java
@@ -348,7 +348,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final DragView dragView = (DragView) dragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
+ float t = (Float) animation.getAnimatedValue();
float tp = scaleAlphaInterpolator.getInterpolation(t);
float initialScale = dragView.getInitialScale();
float finalAlpha = 0.5f;
@@ -396,7 +396,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final DragView dragView = (DragView) mDragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
+ float t = (Float) animation.getAnimatedValue();
long curTime = AnimationUtils.currentAnimationTimeMillis();
if (!mHasOffsetForScale) {
@@ -420,7 +420,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
mVelocity.y *= mFriction;
mPrevTime = curTime;
}
- };
+ }
private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
DragObject d, PointF vel, final long startTime, final int duration,
ViewConfiguration config) {
diff --git a/src/com/cyanogenmod/trebuchet/DragController.java b/src/com/cyanogenmod/trebuchet/DragController.java
index da75b8f..071948c 100644
--- a/src/com/cyanogenmod/trebuchet/DragController.java
+++ b/src/com/cyanogenmod/trebuchet/DragController.java
@@ -33,8 +33,6 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.inputmethod.InputMethodManager;
-import com.cyanogenmod.trebuchet.R;
-
import java.util.ArrayList;
/**
@@ -519,7 +517,7 @@ public class DragController {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE;
if (mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) {
- mLauncher.getDragLayer().onEnterScrollArea(SCROLL_LEFT);
+ mLauncher.getDragLayer().onEnterScrollArea();
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, delay);
}
@@ -528,7 +526,7 @@ public class DragController {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE;
if (mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) {
- mLauncher.getDragLayer().onEnterScrollArea(SCROLL_RIGHT);
+ mLauncher.getDragLayer().onEnterScrollArea();
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.postDelayed(mScrollRunnable, delay);
}
diff --git a/src/com/cyanogenmod/trebuchet/DragLayer.java b/src/com/cyanogenmod/trebuchet/DragLayer.java
index 892cd48..420dfd5 100644
--- a/src/com/cyanogenmod/trebuchet/DragLayer.java
+++ b/src/com/cyanogenmod/trebuchet/DragLayer.java
@@ -104,18 +104,12 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
- return false;
+ return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder, mHitRect);
- if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
- return true;
- }
- return false;
+ return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
@@ -732,7 +726,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private Drawable mLeftHoverDrawable;
private Drawable mRightHoverDrawable;
- void onEnterScrollArea(int direction) {
+ void onEnterScrollArea() {
mInScrollArea = true;
invalidate();
}
diff --git a/src/com/cyanogenmod/trebuchet/FocusHelper.java b/src/com/cyanogenmod/trebuchet/FocusHelper.java
index d87fc67..0ac6e24 100644
--- a/src/com/cyanogenmod/trebuchet/FocusHelper.java
+++ b/src/com/cyanogenmod/trebuchet/FocusHelper.java
@@ -139,7 +139,7 @@ public class FocusHelper {
final TabWidget tabs = tabHost.getTabWidget();
final int widgetIndex = parent.indexOfChild(w);
final int widgetCount = parent.getChildCount();
- final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent));
+ final int pageIndex = container.indexToPage(container.indexOfChild(parent));
final int pageCount = container.getChildCount();
final int cellCountX = parent.getCellCountX();
final int cellCountY = parent.getCellCountY();
@@ -148,7 +148,7 @@ public class FocusHelper {
final int action = e.getAction();
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- ViewGroup newParent = null;
+ ViewGroup newParent;
// Now that we load items in the bg asynchronously, we can't just focus
// child siblings willy-nilly
View child = null;
@@ -299,7 +299,7 @@ public class FocusHelper {
final TabWidget tabs = tabHost.getTabWidget();
final int iconIndex = itemContainer.indexOfChild(v);
final int itemCount = itemContainer.getChildCount();
- final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout));
+ final int pageIndex = container.indexToPage(container.indexOfChild(parentLayout));
final int pageCount = container.getChildCount();
final int x = iconIndex % countX;
@@ -307,10 +307,10 @@ public class FocusHelper {
final int action = e.getAction();
final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- ViewGroup newParent = null;
+ ViewGroup newParent;
// Side pages do not always load synchronously, so check before focusing child siblings
// willy-nilly
- View child = null;
+ View child;
boolean wasHandled = false;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
diff --git a/src/com/cyanogenmod/trebuchet/FocusOnlyTabWidget.java b/src/com/cyanogenmod/trebuchet/FocusOnlyTabWidget.java
index 795b621..96bf589 100644
--- a/src/com/cyanogenmod/trebuchet/FocusOnlyTabWidget.java
+++ b/src/com/cyanogenmod/trebuchet/FocusOnlyTabWidget.java
@@ -72,15 +72,11 @@ public class FocusOnlyTabWidget extends TabWidget {
super.onFocusChange(tab, true);
}
}
- public void superOnFocusChange(View v, boolean hasFocus) {
- super.onFocusChange(v, hasFocus);
- }
@Override
public void onFocusChange(android.view.View v, boolean hasFocus) {
if (v == this && hasFocus && getTabCount() > 0) {
getSelectedTab().requestFocus();
- return;
}
}
}
diff --git a/src/com/cyanogenmod/trebuchet/Folder.java b/src/com/cyanogenmod/trebuchet/Folder.java
index 465f32c..d2a9dea 100644
--- a/src/com/cyanogenmod/trebuchet/Folder.java
+++ b/src/com/cyanogenmod/trebuchet/Folder.java
@@ -339,8 +339,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private void placeInReadingOrder(ArrayList<ShortcutInfo> items) {
int maxX = 0;
int count = items.size();
- for (int i = 0; i < count; i++) {
- ShortcutInfo item = items.get(i);
+ for (ShortcutInfo item : items) {
if (item.cellX > maxX) {
maxX = item.cellX;
}
@@ -365,8 +364,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
setupContentForNumItems(children.size());
placeInReadingOrder(children);
int count = 0;
- for (int i = 0; i < children.size(); i++) {
- ShortcutInfo child = (ShortcutInfo) children.get(i);
+ for (ShortcutInfo child : children) {
if (!createAndAddShortcut(child)) {
overflow.add(child);
} else {
@@ -585,11 +583,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
};
boolean readingOrderGreaterThan(int[] v1, int[] v2) {
- if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
- return true;
- } else {
- return false;
- }
+ return v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0]);
}
private void realTimeReorder(int[] empty, int[] target) {
@@ -750,11 +744,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private void updateItemLocationsInDatabase() {
ArrayList<View> list = getItemsInReadingOrder();
- for (int i = 0; i < list.size(); i++) {
- View v = list.get(i);
+ for (View v : list) {
ItemInfo info = (ItemInfo) v.getTag();
LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
- info.cellX, info.cellY);
+ info.cellX, info.cellY);
}
}
@@ -902,8 +895,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
mContent.removeAllViews();
- for (int i = 0; i < list.size(); i++) {
- View v = list.get(i);
+ for (View v : list) {
mContent.getVacantCell(vacant, 1, 1);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
lp.cellX = vacant[0];
@@ -915,8 +907,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
info.cellX, info.cellY);
}
- boolean insert = false;
- mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
+ mContent.addViewToCellLayout(v, 0, (int) info.id, lp, true);
}
mItemsInvalidated = true;
}
diff --git a/src/com/cyanogenmod/trebuchet/FolderIcon.java b/src/com/cyanogenmod/trebuchet/FolderIcon.java
index e9aaab5..b67e0bd 100644
--- a/src/com/cyanogenmod/trebuchet/FolderIcon.java
+++ b/src/com/cyanogenmod/trebuchet/FolderIcon.java
@@ -41,12 +41,11 @@ import android.widget.TextView;
import com.cyanogenmod.trebuchet.DropTarget.DragObject;
import com.cyanogenmod.trebuchet.FolderInfo.FolderListener;
-import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
import java.util.ArrayList;
/**
- * An icon that can appear on in the workspace representing an {@link UserFolder}.
+ * An icon that can appear on in the workspace representing an {@link Folder}.
*/
public class FolderIcon extends LinearLayout implements FolderListener {
private Launcher mLauncher;
@@ -113,15 +112,8 @@ public class FolderIcon extends LinearLayout implements FolderListener {
mLongPressHelper = new CheckLongPressHelper(this);
}
- public boolean isDropEnabled() {
- final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
- final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
- final Workspace workspace = (Workspace) cellLayout.getParent();
- return !workspace.isSmall();
- }
-
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
- FolderInfo folderInfo, IconCache iconCache) {
+ FolderInfo folderInfo) {
@SuppressWarnings("all") // suppress dead code warning
final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION;
if (error) {
@@ -297,8 +289,8 @@ public class FolderIcon extends LinearLayout implements FolderListener {
!mFolder.isFull() && item != mInfo && !mInfo.opened);
}
- public boolean acceptDrop(Object dragInfo) {
- final ItemInfo item = (ItemInfo) dragInfo;
+ public boolean acceptDrop(ItemInfo dragInfo) {
+ final ItemInfo item = dragInfo;
return !mFolder.isDestroyed() && willAcceptItem(item);
}
@@ -316,9 +308,6 @@ public class FolderIcon extends LinearLayout implements FolderListener {
layout.showFolderAccept(mFolderRingAnimator);
}
- public void onDragOver(Object dragInfo) {
- }
-
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
@@ -334,7 +323,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
addItem(destInfo);
// This will animate the dragView (srcView) into the new folder
- onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable, null);
+ onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
}
public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) {
@@ -348,17 +337,12 @@ public class FolderIcon extends LinearLayout implements FolderListener {
onCompleteRunnable);
}
- public void onDragExit(Object dragInfo) {
- onDragExit();
- }
-
public void onDragExit() {
mFolderRingAnimator.animateToNaturalState();
}
private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
- float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable,
- DragObject d) {
+ float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
item.cellX = -1;
item.cellY = -1;
@@ -388,8 +372,8 @@ public class FolderIcon extends LinearLayout implements FolderListener {
int[] center = new int[2];
float scale = getLocalCenterForIndex(index, center);
- center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
- center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
+ center[0] = Math.round(scaleRelativeToDragLayer * center[0]);
+ center[1] = Math.round(scaleRelativeToDragLayer * center[1]);
to.offset(center[0] - animateView.getMeasuredWidth() / 2,
center[1] - animateView.getMeasuredHeight() / 2);
@@ -423,7 +407,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
FolderInfo folder = (FolderInfo) d.dragInfo;
mFolder.notifyDrop();
for (ShortcutInfo fItem : folder.contents) {
- onDrop(fItem, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d);
+ onDrop(fItem, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
}
mLauncher.removeFolder(folder);
LauncherModel.deleteItemFromDatabase(mLauncher, folder);
@@ -432,11 +416,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
item = (ShortcutInfo) d.dragInfo;
}
mFolder.notifyDrop();
- onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d);
- }
-
- public DropTarget getDropTargetDelegate(DragObject d) {
- return null;
+ onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
}
private void computePreviewDrawingParams(int drawableSize, int totalSize) {
@@ -488,8 +468,8 @@ public class FolderIcon extends LinearLayout implements FolderListener {
float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2;
float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2;
- center[0] = (int) Math.round(offsetX);
- center[1] = (int) Math.round(offsetY);
+ center[0] = Math.round(offsetX);
+ center[1] = Math.round(offsetY);
return mParams.scale;
}
diff --git a/src/com/cyanogenmod/trebuchet/FolderInfo.java b/src/com/cyanogenmod/trebuchet/FolderInfo.java
index 710b137..7c6941b 100644
--- a/src/com/cyanogenmod/trebuchet/FolderInfo.java
+++ b/src/com/cyanogenmod/trebuchet/FolderInfo.java
@@ -48,8 +48,8 @@ class FolderInfo extends ItemInfo {
*/
public void add(ShortcutInfo item) {
contents.add(item);
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onAdd(item);
+ for (FolderListener listener : listeners) {
+ listener.onAdd(item);
}
itemsChanged();
}
@@ -61,16 +61,16 @@ class FolderInfo extends ItemInfo {
*/
public void remove(ShortcutInfo item) {
contents.remove(item);
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onRemove(item);
+ for (FolderListener listener : listeners) {
+ listener.onRemove(item);
}
itemsChanged();
}
public void setTitle(CharSequence title) {
this.title = title;
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onTitleChanged(title);
+ for (FolderListener listener : listeners) {
+ listener.onTitleChanged(title);
}
}
@@ -91,8 +91,8 @@ class FolderInfo extends ItemInfo {
}
void itemsChanged() {
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onItemsChanged();
+ for (FolderListener listener : listeners) {
+ listener.onItemsChanged();
}
}
diff --git a/src/com/cyanogenmod/trebuchet/HandleView.java b/src/com/cyanogenmod/trebuchet/HandleView.java
deleted file mode 100644
index 8944888..0000000
--- a/src/com/cyanogenmod/trebuchet/HandleView.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.cyanogenmod.trebuchet;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageView;
-
-import com.cyanogenmod.trebuchet.R;
-
-public class HandleView extends ImageView {
- private static final int ORIENTATION_HORIZONTAL = 1;
-
- private Launcher mLauncher;
- private int mOrientation = ORIENTATION_HORIZONTAL;
-
- public HandleView(Context context) {
- super(context);
- }
-
- public HandleView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public HandleView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HandleView, defStyle, 0);
- mOrientation = a.getInt(R.styleable.HandleView_direction, ORIENTATION_HORIZONTAL);
- a.recycle();
-
- setContentDescription(context.getString(R.string.all_apps_button_label));
- }
-
- @Override
- public View focusSearch(int direction) {
- View newFocus = super.focusSearch(direction);
- if (newFocus == null && !mLauncher.isAllAppsVisible()) {
- final Workspace workspace = mLauncher.getWorkspace();
- workspace.dispatchUnhandledMove(null, direction);
- return (mOrientation == ORIENTATION_HORIZONTAL && direction == FOCUS_DOWN) ?
- this : workspace;
- }
- return newFocus;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
- return false;
- }
- return super.onTouchEvent(ev);
- }
-
- void setLauncher(Launcher launcher) {
- mLauncher = launcher;
- }
-}
diff --git a/src/com/cyanogenmod/trebuchet/Hotseat.java b/src/com/cyanogenmod/trebuchet/Hotseat.java
index 600c254..d52cb0c 100644
--- a/src/com/cyanogenmod/trebuchet/Hotseat.java
+++ b/src/com/cyanogenmod/trebuchet/Hotseat.java
@@ -18,19 +18,14 @@ package com.cyanogenmod.trebuchet;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
public class Hotseat extends PagedView {
- private Launcher mLauncher;
- private CellLayout mContent;
-
private int mCellCount;
private boolean mTransposeLayoutWithOrientation;
@@ -83,10 +78,7 @@ public class Hotseat extends PagedView {
// No data needed
setDataIsReady();
- }
- public void setup(Launcher launcher) {
- mLauncher = launcher;
setOnKeyListener(new HotseatIconKeyEventListener());
}
diff --git a/src/com/cyanogenmod/trebuchet/InstallShortcutReceiver.java b/src/com/cyanogenmod/trebuchet/InstallShortcutReceiver.java
index c9627d7..10bdb72 100644
--- a/src/com/cyanogenmod/trebuchet/InstallShortcutReceiver.java
+++ b/src/com/cyanogenmod/trebuchet/InstallShortcutReceiver.java
@@ -190,7 +190,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
}
synchronized (newApps) {
- newApps.add(intent.toUri(0).toString());
+ newApps.add(intent.toUri(0));
}
final Set<String> savedNewApps = newApps;
new Thread("setNewAppsThread") {
@@ -231,10 +231,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
final int yCount = LauncherModel.getCellCountY();
boolean[][] occupied = new boolean[xCount][yCount];
- ItemInfo item = null;
int cellX, cellY, spanX, spanY;
- for (int i = 0; i < items.size(); ++i) {
- item = items.get(i);
+ for (ItemInfo item : items) {
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (item.screen == screen) {
cellX = item.cellX;
diff --git a/src/com/cyanogenmod/trebuchet/InterruptibleInOutAnimator.java b/src/com/cyanogenmod/trebuchet/InterruptibleInOutAnimator.java
index 8183ce4..ea847d7 100644
--- a/src/com/cyanogenmod/trebuchet/InterruptibleInOutAnimator.java
+++ b/src/com/cyanogenmod/trebuchet/InterruptibleInOutAnimator.java
@@ -62,7 +62,7 @@ public class InterruptibleInOutAnimator {
final long currentPlayTime = mAnimator.getCurrentPlayTime();
final float toValue = (direction == IN) ? mOriginalToValue : mOriginalFromValue;
final float startValue = mFirstRun ? mOriginalFromValue :
- ((Float) mAnimator.getAnimatedValue()).floatValue();
+ (Float) mAnimator.getAnimatedValue();
// Make sure it's stopped before we modify any values
cancel();
diff --git a/src/com/cyanogenmod/trebuchet/ItemInfo.java b/src/com/cyanogenmod/trebuchet/ItemInfo.java
index 794903c..11be869 100644
--- a/src/com/cyanogenmod/trebuchet/ItemInfo.java
+++ b/src/com/cyanogenmod/trebuchet/ItemInfo.java
@@ -23,6 +23,7 @@ import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Arrays;
/**
* Represents an item in the launcher.
@@ -189,6 +190,6 @@ class ItemInfo {
public String toString() {
return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
+ " screen=" + screen + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
- + " spanY=" + spanY + " dropPos=" + dropPos + ")";
+ + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + ")";
}
}
diff --git a/src/com/cyanogenmod/trebuchet/Launcher.java b/src/com/cyanogenmod/trebuchet/Launcher.java
index e8efcc6..5318766 100644
--- a/src/com/cyanogenmod/trebuchet/Launcher.java
+++ b/src/com/cyanogenmod/trebuchet/Launcher.java
@@ -44,7 +44,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.Intent.ShortcutIconResource;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -100,7 +99,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.common.Search;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.DropTarget.DragObject;
import com.cyanogenmod.trebuchet.preference.*;
@@ -127,7 +125,6 @@ public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
private static final String TAG = "Trebuchet.Launcher";
- static final boolean LOGD = false;
static final boolean PROFILE_STARTUP = false;
static final boolean DEBUG_WIDGETS = false;
@@ -160,7 +157,6 @@ public final class Launcher extends Activity
static final int DIALOG_CREATE_ACTION = 2;
private static final String PREFERENCES = "launcher.preferences";
- static final String FORCE_ENABLE_ROTATION_PROPERTY = "debug.force_enable_rotation";
static final String DUMP_STATE_PROPERTY = "debug.dumpstate";
// The Intent extra that defines whether to ignore the launch animation
@@ -197,7 +193,7 @@ public final class Launcher extends Activity
"com.android.launcher.toolbar_voice_search_icon";
/** The different states that Launcher can be in. */
- private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
+ private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED }
private State mState = State.WORKSPACE;
private AnimatorSet mStateAnimation;
private AnimatorSet mDividerAnimator;
@@ -208,11 +204,8 @@ public final class Launcher extends Activity
private static final int SHOW_CLING_DURATION = 550;
private static final int DISMISS_CLING_DURATION = 250;
- private static final Object sLock = new Object();
- private static int sScreen = DEFAULT_SCREEN;
-
// How long to wait before the new-shortcut animation automatically pans the workspace
- private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10;
+ private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10;
private final BroadcastReceiver mCloseSystemDialogsReceiver
= new CloseSystemDialogsIntentReceiver();
@@ -237,7 +230,6 @@ public final class Launcher extends Activity
private FolderInfo mFolderInfo;
private Hotseat mHotseat;
- private View mAllAppsButton;
private SearchDropTargetBar mSearchDropTargetBar;
private AppsCustomizeTabHost mAppsCustomizeTabHost;
@@ -262,8 +254,6 @@ public final class Launcher extends Activity
// Keep track of whether the user has left launcher
private static boolean sPausedFromUserAction = false;
- private Bundle mSavedInstanceState;
-
private LauncherModel mModel;
private IconCache mIconCache;
private boolean mUserPresent = true;
@@ -287,7 +277,7 @@ public final class Launcher extends Activity
// Determines how long to wait after a rotation before restoring the screen orientation to
// match the sensor state.
- private final int mRestoreScreenOrientationDelay = 500;
+ private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500;
// External icons saved in case of resource changes, orientation, etc.
private static Drawable.ConstantState[] sGlobalSearchIcon = new Drawable.ConstantState[2];
@@ -346,7 +336,7 @@ public final class Launcher extends Activity
private boolean doesFileExist(String filename) {
- FileInputStream fis = null;
+ FileInputStream fis;
try {
fis = openFileInput(filename);
fis.close();
@@ -601,18 +591,6 @@ public final class Launcher extends Activity
return !mModel.isLoadingWorkspace();
}
- static int getScreen() {
- synchronized (sLock) {
- return sScreen;
- }
- }
-
- static void setScreen(int screen) {
- synchronized (sLock) {
- sScreen = screen;
- }
- }
-
/**
* Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
* a configuration step, this allows the proper animations to run after other transitions.
@@ -710,8 +688,7 @@ public final class Launcher extends Activity
public void run() {
completeAddAppWidget(appWidgetId, mPendingAddInfo.container,
mPendingAddInfo.screen, layout, null);
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
+ exitSpringLoadedDragModeDelayed(true, false, null);
}
};
} else if (resultCode == RESULT_CANCELED) {
@@ -719,8 +696,7 @@ public final class Launcher extends Activity
onCompleteRunnable = new Runnable() {
@Override
public void run() {
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
+ exitSpringLoadedDragModeDelayed(false, false, null);
}
};
}
@@ -730,7 +706,9 @@ public final class Launcher extends Activity
animationType, boundWidget, true);
} else {
// The animated view may be null in the case of a rotation during widget configuration
- onCompleteRunnable.run();
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
}
}
@@ -857,9 +835,9 @@ public final class Launcher extends Activity
private static State intToState(int stateOrdinal) {
State state = State.WORKSPACE;
final State[] stateValues = State.values();
- for (int i = 0; i < stateValues.length; i++) {
- if (stateValues[i].ordinal() == stateOrdinal) {
- state = stateValues[i];
+ for (State stateValue : stateValues) {
+ if (stateValue.ordinal() == stateOrdinal) {
+ state = stateValue;
break;
}
}
@@ -933,17 +911,14 @@ public final class Launcher extends Activity
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
- mQsbDivider = (ImageView) findViewById(R.id.qsb_divider);
- mDockDivider = (ImageView) findViewById(R.id.dock_divider);
+ mQsbDivider = findViewById(R.id.qsb_divider);
+ mDockDivider = findViewById(R.id.dock_divider);
// Setup the drag layer
mDragLayer.setup(this, dragController);
// Setup the hotseat
mHotseat = (Hotseat) findViewById(R.id.hotseat);
- if (mHotseat != null) {
- mHotseat.setup(this);
- }
// Setup the workspace
mWorkspace.setHapticFeedbackEnabled(false);
@@ -956,11 +931,11 @@ public final class Launcher extends Activity
// Hide the search divider if we are hiding search bar
if (!mShowSearchBar && getCurrentOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
- ((View) findViewById(R.id.qsb_divider)).setVisibility(View.GONE);
+ findViewById(R.id.qsb_divider).setVisibility(View.GONE);
}
if (!mShowDockDivider) {
- ((View) findViewById(R.id.dock_divider)).setVisibility(View.GONE);
+ findViewById(R.id.dock_divider).setVisibility(View.GONE);
}
// Setup AppsCustomize
@@ -1061,7 +1036,7 @@ public final class Launcher extends Activity
info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
info.container = ItemInfo.NO_ID;
- mWorkspace.addApplicationShortcut(info, layout, container, screen, cellXY[0], cellXY[1],
+ mWorkspace.addApplicationShortcut(info, layout, container, screen,
isWorkspaceLocked(), cellX, cellY);
} else {
Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
@@ -1080,7 +1055,7 @@ public final class Launcher extends Activity
int[] touchXY = mPendingAddInfo.dropPos;
CellLayout layout = getCellLayout(container, screen);
- boolean foundCellSpan = false;
+ boolean foundCellSpan;
ShortcutInfo info = mModel.infoFromShortcutIntent(this, data, null);
if (info == null) {
@@ -1101,7 +1076,7 @@ public final class Launcher extends Activity
}
DragObject dragObject = new DragObject();
dragObject.dragInfo = info;
- if (mWorkspace.addToExistingFolderIfNecessary(view, layout, cellXY, 0, dragObject,
+ if (mWorkspace.addToExistingFolderIfNecessary(layout, cellXY, 0, dragObject,
true)) {
return;
}
@@ -1177,7 +1152,7 @@ public final class Launcher extends Activity
int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mPendingAddInfo.dropPos;
int[] finalSpan = new int[2];
- boolean foundCellSpan = false;
+ boolean foundCellSpan;
if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
cellXY[0] = mPendingAddInfo.cellX;
cellXY[1] = mPendingAddInfo.cellY;
@@ -1251,7 +1226,7 @@ public final class Launcher extends Activity
int screen = mPendingAddInfo.screen;
CellLayout layout = getCellLayout(container, screen);
- boolean foundCellSpan = false;
+ boolean foundCellSpan;
Intent data = createActionIntent(action);
@@ -1277,7 +1252,7 @@ public final class Launcher extends Activity
}
DragObject dragObject = new DragObject();
dragObject.dragInfo = info;
- if (mWorkspace.addToExistingFolderIfNecessary(view, layout, cellXY, 0, dragObject,
+ if (mWorkspace.addToExistingFolderIfNecessary(layout, cellXY, 0, dragObject,
true)) {
return;
}
@@ -1291,14 +1266,13 @@ public final class Launcher extends Activity
if (!foundCellSpan) {
showOutOfSpaceMessage(isHotseatLayout(layout));
- return;
- }
-
- LauncherModel.addItemToDatabase(this, info, container, screen, cellXY[0], cellXY[1], false);
+ } else if (cellXY != null) {
+ LauncherModel.addItemToDatabase(this, info, container, screen, cellXY[0], cellXY[1], false);
- if (!mRestoring) {
- mWorkspace.addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1,
- isWorkspaceLocked());
+ if (!mRestoring) {
+ mWorkspace.addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1,
+ isWorkspaceLocked());
+ }
}
}
@@ -1663,7 +1637,7 @@ public final class Launcher extends Activity
/**
* Indicates that we want global search for this activity by setting the globalSearch
- * argument for {@link #startSearch} to true.
+ * argument for startSearch to true.
*/
@Override
public void startSearch(String initialQuery, boolean selectInitialQuery,
@@ -1945,7 +1919,7 @@ public final class Launcher extends Activity
appWidgetId = getAppWidgetHost().allocateAppWidgetId();
Bundle options = info.bindOptions;
- boolean success = false;
+ boolean success;
if (options != null) {
success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
info.componentName, options);
@@ -1987,7 +1961,7 @@ public final class Launcher extends Activity
// Create the view
FolderIcon newFolder =
- FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
+ FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo);
if (mHideIconLabels) {
newFolder.setTextVisible(false);
}
@@ -2005,18 +1979,7 @@ public final class Launcher extends Activity
final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
Intent chooser = Intent.createChooser(pickWallpaper,
getText(R.string.chooser_wallpaper));
- // NOTE: Adds a configure option to the chooser if the wallpaper supports it
- // Removed in Eclair MR1
-// WallpaperManager wm = (WallpaperManager)
-// getSystemService(Context.WALLPAPER_SERVICE);
-// WallpaperInfo wi = wm.getWallpaperInfo();
-// if (wi != null && wi.getSettingsActivity() != null) {
-// LabeledIntent li = new LabeledIntent(getPackageName(),
-// R.string.configure_wallpaper, 0);
-// li.setClassName(wi.getPackageName(), wi.getSettingsActivity());
-// chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { li });
-// }
- startActivityForResult(chooser, REQUEST_PICK_WALLPAPER);
+ processWallpaper(chooser);
}
/**
@@ -2116,12 +2079,6 @@ public final class Launcher extends Activity
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
- } else if (v == mAllAppsButton) {
- if (isAllAppsVisible()) {
- showWorkspace(true);
- } else {
- onClickAllAppsButton(v);
- }
}
}
@@ -2168,21 +2125,6 @@ public final class Launcher extends Activity
}
}
- /**
- * Event handler for the "grid" button that appears on the home screen, which
- * enters all apps mode.
- *
- * @param v The view that was clicked.
- */
- public void onClickAllAppsButton(View v) {
- showAllApps(true);
- }
-
- public void onTouchDownAllAppsButton(View v) {
- // Provide the same haptic feedback that the system offers for virtual keys.
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
-
public void onClickAppMarketButton(View v) {
if (mAppMarketIntent != null) {
startActivitySafely(v, mAppMarketIntent, "app market");
@@ -2478,7 +2420,7 @@ public final class Launcher extends Activity
// There was a one-off crash where the folder had a parent already.
if (folder.getParent() == null) {
mDragLayer.addView(folder);
- mDragController.addDropTarget((DropTarget) folder);
+ mDragController.addDropTarget(folder);
} else {
Log.w(TAG, "Opening folder (" + folder + ") which already has a parent (" +
folder.getParent() + ").");
@@ -2639,10 +2581,9 @@ public final class Launcher extends Activity
/**
* Helper method for the cameraZoomIn/cameraZoomOut animations
* @param view The view being animated
- * @param state The state that we are moving in or out of (eg. APPS_CUSTOMIZE)
- * @param scaleFactor The scale factor used for the zoom
+ *
*/
- private void setPivotsForZoom(View view, float scaleFactor) {
+ private void setPivotsForZoom(View view) {
view.setPivotX(view.getWidth() / 2.0f);
view.setPivotY(view.getHeight() / 2.0f);
}
@@ -2770,7 +2711,7 @@ public final class Launcher extends Activity
final int startDelay =
res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
- setPivotsForZoom(toView, scale);
+ setPivotsForZoom(toView);
// Shrink workspaces away if going to AppsCustomize from workspace
Animator workspaceAnim =
@@ -2859,7 +2800,7 @@ public final class Launcher extends Activity
// If any of the objects being animated haven't been measured/laid out
// yet, delay the animation until we get a layout pass
- if ((((LauncherTransitionable) toView).getContent().getMeasuredWidth() == 0) ||
+ if ((toView.getContent().getMeasuredWidth() == 0) ||
(mWorkspace.getMeasuredWidth() == 0) ||
(toView.getMeasuredWidth() == 0)) {
observer = mWorkspace.getViewTreeObserver();
@@ -2875,7 +2816,7 @@ public final class Launcher extends Activity
// we waited for a layout/draw pass
if (mStateAnimation != stateAnimation)
return;
- setPivotsForZoom(toView, scale);
+ setPivotsForZoom(toView);
dispatchOnLauncherTransitionStart(fromView, animated, false);
dispatchOnLauncherTransitionStart(toView, animated, false);
toView.post(new Runnable() {
@@ -2934,7 +2875,7 @@ public final class Launcher extends Activity
* @param animated If true, the transition will be animated.
*/
private void hideAppsCustomizeHelper(State toState, final boolean animated,
- final boolean springLoaded, final Runnable onCompleteRunnable) {
+ final Runnable onCompleteRunnable) {
if (mStateAnimation != null) {
mStateAnimation.cancel();
@@ -2960,7 +2901,7 @@ public final class Launcher extends Activity
Workspace.State.SPRING_LOADED, animated);
}
- setPivotsForZoom(fromView, scaleFactor);
+ setPivotsForZoom(fromView);
updateWallpaperVisibility(true);
showHotseat(animated);
if (animated) {
@@ -3071,7 +3012,7 @@ public final class Launcher extends Activity
if (mState != State.WORKSPACE) {
boolean wasInSpringLoadedMode = (mState == State.APPS_CUSTOMIZE_SPRING_LOADED);
mWorkspace.setVisibility(View.VISIBLE);
- hideAppsCustomizeHelper(State.WORKSPACE, animated, false, onCompleteRunnable);
+ hideAppsCustomizeHelper(State.WORKSPACE, animated, onCompleteRunnable);
// Show the search bar (only animate if we were showing the drop target bar in spring
// loaded mode)
@@ -3081,11 +3022,6 @@ public final class Launcher extends Activity
// We only need to animate in the dock divider if we're going from spring loaded mode
showDockDivider(animated && wasInSpringLoadedMode);
-
- // Set focus to the AppsCustomize button
- if (mAllAppsButton != null) {
- mAllAppsButton.requestFocus();
- }
}
mWorkspace.flashScrollingIndicator(animated);
@@ -3123,7 +3059,7 @@ public final class Launcher extends Activity
void enterSpringLoadedDragMode() {
if (isAllAppsVisible()) {
- hideAppsCustomizeHelper(State.APPS_CUSTOMIZE_SPRING_LOADED, true, true, null);
+ hideAppsCustomizeHelper(State.APPS_CUSTOMIZE_SPRING_LOADED, true, null);
hideDockDivider();
mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
}
@@ -3248,16 +3184,6 @@ public final class Launcher extends Activity
}
}
- /**
- * Add an item from all apps or customize onto the given workspace screen.
- * If layout is null, add to the current screen.
- */
- void addExternalItemToScreen(ItemInfo itemInfo, final CellLayout layout) {
- if (!mWorkspace.addExternalItemToScreen(itemInfo, layout)) {
- showOutOfSpaceMessage(isHotseatLayout(layout));
- }
- }
-
public int getCurrentOrientation() {
return getResources().getConfiguration().orientation;
}
@@ -3406,7 +3332,7 @@ public final class Launcher extends Activity
private void updateGlobalSearchIcon(Drawable.ConstantState d) {
final View searchButtonContainer = findViewById(R.id.search_button_container);
- final View searchButton = (ImageView) findViewById(R.id.search_button);
+ final View searchButton = findViewById(R.id.search_button);
updateButtonWithDrawable(R.id.search_button, d);
invalidatePressedFocusedStates(searchButtonContainer, searchButton);
}
@@ -3770,7 +3696,7 @@ public final class Launcher extends Activity
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
ShortcutInfo info = (ShortcutInfo) item;
- String uri = info.intent.toUri(0).toString();
+ String uri = info.intent.toUri(0);
View shortcut = createShortcut(info);
workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
item.cellY, 1, 1, false);
@@ -3794,7 +3720,7 @@ public final class Launcher extends Activity
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
- (FolderInfo) item, mIconCache);
+ (FolderInfo) item);
if (!mHideIconLabels) {
newFolder.setTextVisible(false);
}
@@ -3876,8 +3802,8 @@ public final class Launcher extends Activity
// If we received the result of any pending adds while the loader was running (e.g. the
// widget configuration forced an orientation change), process them now.
- for (int i = 0; i < sPendingAddList.size(); i++) {
- completeAdd(sPendingAddList.get(i));
+ for (PendingAddArguments pendingAdd : sPendingAddList) {
+ completeAdd(pendingAdd);
}
sPendingAddList.clear();
@@ -3956,7 +3882,7 @@ public final class Launcher extends Activity
PropertyValuesHolder.ofFloat("scaleY", 1f));
bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
- bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
+ bounceAnim.setInterpolator(new PagedView.OvershootInterpolator());
bounceAnims.add(bounceAnim);
}
anim.playTogether(bounceAnims);
@@ -4115,20 +4041,14 @@ public final class Launcher extends Activity
return oriMap[(d.getRotation() + indexOffset) % 4];
}
- public boolean isRotationEnabled() {
- boolean forceEnableRotation = doesFileExist(FORCE_ENABLE_ROTATION_PROPERTY);
- boolean enableRotation = forceEnableRotation ||
- getResources().getBoolean(R.bool.allow_rotation) || mAutoRotate;
- return enableRotation;
- }
public void lockScreenOrientation() {
- if (isRotationEnabled()) {
+ if (mAutoRotate) {
setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
.getConfiguration().orientation));
}
}
public void unlockScreenOrientation(boolean immediate) {
- if (isRotationEnabled()) {
+ if (mAutoRotate) {
if (immediate) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} else {
@@ -4136,7 +4056,7 @@ public final class Launcher extends Activity
public void run() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
- }, mRestoreScreenOrientationDelay);
+ }, RESTORE_SCREEN_ORIENTATION_DELAY);
}
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
@@ -4146,9 +4066,8 @@ public final class Launcher extends Activity
/* Cling related */
private boolean isClingsEnabled() {
// disable clings when running in a test harness
- if(ActivityManager.isRunningInTestHarness()) return false;
+ return !ActivityManager.isRunningInTestHarness();
- return true;
}
private Cling initCling(int clingId, int[] positionData, boolean animate, int delay) {
@@ -4199,7 +4118,7 @@ public final class Launcher extends Activity
editor.commit();
}
}.start();
- };
+ }
});
anim.start();
mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
@@ -4286,10 +4205,7 @@ public final class Launcher extends Activity
}
public boolean isFolderClingVisible() {
Cling cling = (Cling) findViewById(R.id.folder_cling);
- if (cling != null) {
- return cling.getVisibility() == View.VISIBLE;
- }
- return false;
+ return cling != null && cling.getVisibility() == View.VISIBLE;
}
public void dismissWorkspaceCling(View v) {
Cling cling = (Cling) findViewById(R.id.workspace_cling);
@@ -4329,7 +4245,7 @@ public final class Launcher extends Activity
Log.d(TAG, "mWorkspaceLoading=" + mWorkspaceLoading);
Log.d(TAG, "mRestoring=" + mRestoring);
Log.d(TAG, "mWaitingForResult=" + mWaitingForResult);
- Log.d(TAG, "mSavedInstanceState=" + mSavedInstanceState);
+ Log.d(TAG, "mSavedInstanceState=" + mSavedState);
Log.d(TAG, "sFolders.size=" + sFolders.size());
mModel.dumpState();
@@ -4344,8 +4260,8 @@ public final class Launcher extends Activity
super.dump(prefix, fd, writer, args);
writer.println(" ");
writer.println("Debug logs: ");
- for (int i = 0; i < sDumpLogs.size(); i++) {
- writer.println(" " + sDumpLogs.get(i));
+ for (String dumpLog : sDumpLogs) {
+ writer.println(" " + dumpLog);
}
}
@@ -4353,8 +4269,8 @@ public final class Launcher extends Activity
Log.d(TAG, "");
Log.d(TAG, "*********************");
Log.d(TAG, "Launcher debug logs: ");
- for (int i = 0; i < sDumpLogs.size(); i++) {
- Log.d(TAG, " " + sDumpLogs.get(i));
+ for (String dumpLog : sDumpLogs) {
+ Log.d(TAG, " " + dumpLog);
}
Log.d(TAG, "*********************");
Log.d(TAG, "");
diff --git a/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java b/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java
index 81c218b..d87c536 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java
@@ -56,10 +56,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView {
public boolean orientationChangedSincedInflation() {
int orientation = mContext.getResources().getConfiguration().orientation;
- if (mPreviousOrientation != orientation) {
- return true;
- }
- return false;
+ return mPreviousOrientation != orientation;
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
diff --git a/src/com/cyanogenmod/trebuchet/LauncherModel.java b/src/com/cyanogenmod/trebuchet/LauncherModel.java
index 36a8043..fdcaba1 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherModel.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherModel.java
@@ -27,7 +27,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -47,13 +46,11 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
-import com.cyanogenmod.trebuchet.R;
-import com.cyanogenmod.trebuchet.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
-
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.text.Collator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -68,13 +65,11 @@ import java.util.Set;
* for the Launcher.
*/
public class LauncherModel extends BroadcastReceiver {
- static final boolean DEBUG_LOADERS = false;
+ private static final boolean DEBUG_LOADERS = false;
private static final String TAG = "Trebuchet.LauncherModel";
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
private final boolean mAppsCanBeOnExternalStorage;
- private int mBatchSize; // 0 is all apps at once
- private int mAllAppsLoadDelay; // milliseconds between batches
private final LauncherApplication mApp;
private final Object mLock = new Object();
@@ -173,8 +168,6 @@ public class LauncherModel extends BroadcastReceiver {
mIconCache.getFullResDefaultActivityIcon(), app);
final Resources res = app.getResources();
- mAllAppsLoadDelay = res.getInteger(R.integer.config_allAppsBatchLoadDelay);
- mBatchSize = res.getInteger(R.integer.config_allAppsBatchSize);
Configuration config = res.getConfiguration();
mPreviousConfigMcc = config.mcc;
}
@@ -182,9 +175,6 @@ public class LauncherModel extends BroadcastReceiver {
/** Runs the specified runnable immediately if called from the main thread, otherwise it is
* posted on the main thread handler. */
private void runOnMainThread(Runnable r) {
- runOnMainThread(r, 0);
- }
- private void runOnMainThread(Runnable r, int type) {
if (sWorkerThread.getThreadId() == Process.myTid()) {
// If we are on the worker thread, post onto the main handler
mHandler.post(r);
@@ -318,7 +308,7 @@ public class LauncherModel extends BroadcastReceiver {
}
static void updateItemInDatabaseHelper(Context context, final ContentValues values,
- final ItemInfo item, final String callingFunction) {
+ final ItemInfo item) {
final long itemId = item.id;
final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);
final ContentResolver cr = context.getContentResolver();
@@ -393,7 +383,7 @@ public class LauncherModel extends BroadcastReceiver {
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
values.put(LauncherSettings.Favorites.SCREEN, item.screen);
- updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
+ updateItemInDatabaseHelper(context, values, item);
}
/**
@@ -428,7 +418,7 @@ public class LauncherModel extends BroadcastReceiver {
values.put(LauncherSettings.Favorites.SPANY, item.spanY);
values.put(LauncherSettings.Favorites.SCREEN, item.screen);
- updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");
+ updateItemInDatabaseHelper(context, values, item);
}
/**
@@ -438,7 +428,7 @@ public class LauncherModel extends BroadcastReceiver {
final ContentValues values = new ContentValues();
item.onAddToDatabase(values);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
- updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
+ updateItemInDatabaseHelper(context, values, item);
}
/**
@@ -527,12 +517,14 @@ public class LauncherModel extends BroadcastReceiver {
break;
}
- folderInfo.title = c.getString(titleIndex);
- folderInfo.id = id;
- folderInfo.container = c.getInt(containerIndex);
- folderInfo.screen = c.getInt(screenIndex);
- folderInfo.cellX = c.getInt(cellXIndex);
- folderInfo.cellY = c.getInt(cellYIndex);
+ if (folderInfo != null) {
+ folderInfo.title = c.getString(titleIndex);
+ folderInfo.id = id;
+ folderInfo.container = c.getInt(containerIndex);
+ folderInfo.screen = c.getInt(screenIndex);
+ folderInfo.cellX = c.getInt(cellXIndex);
+ folderInfo.cellY = c.getInt(cellYIndex);
+ }
return folderInfo;
}
@@ -564,8 +556,6 @@ public class LauncherModel extends BroadcastReceiver {
values.put(LauncherSettings.Favorites._ID, item.id);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
- final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
-
Runnable r = new Runnable() {
public void run() {
String transaction = "DbDebug Add item (" + item.title + ") to db, id: "
@@ -613,8 +603,7 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Creates a new unique child id, for a given cell span across all layouts.
*/
- static int getCellLayoutChildId(
- long container, int screen, int localCellX, int localCellY, int spanX, int spanY) {
+ static int getCellLayoutChildId(long container, int screen, int localCellX, int localCellY) {
return (((int) container & 0xFF) << 24)
| (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
}
@@ -1048,7 +1037,7 @@ public class LauncherModel extends BroadcastReceiver {
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
final Callbacks cbk = mCallbacks.get();
- final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
+ final boolean loadWorkspaceFirst = cbk == null || !cbk.isAllAppsVisible();
keep_running: {
// Elevate priority when Home launches for the first time to avoid
@@ -1609,7 +1598,7 @@ public class LauncherModel extends BroadcastReceiver {
if (postOnMainThread) {
deferredBindRunnables.add(r);
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -1626,7 +1615,7 @@ public class LauncherModel extends BroadcastReceiver {
if (postOnMainThread) {
deferredBindRunnables.add(r);
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -1645,7 +1634,7 @@ public class LauncherModel extends BroadcastReceiver {
if (postOnMainThread) {
deferredBindRunnables.add(r);
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
}
@@ -1713,7 +1702,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
};
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
// Load items on the current page
bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
@@ -1727,7 +1716,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
};
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
// Load all the remaining pages (if we are loading synchronously, we want to defer this
@@ -1756,7 +1745,7 @@ public class LauncherModel extends BroadcastReceiver {
if (isLoadingSynchronously) {
mDeferredBindRunnables.add(r);
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -1825,102 +1814,64 @@ public class LauncherModel extends BroadcastReceiver {
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- final PackageManager packageManager = mContext.getPackageManager();
- List<ResolveInfo> apps = null;
-
- int N = Integer.MAX_VALUE;
-
- int startIndex;
- int i=0;
- int batchSize = -1;
- while (i < N && !mStopped) {
- if (i == 0) {
- mBgAllAppsList.clear();
- final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- apps = packageManager.queryIntentActivities(mainIntent, 0);
- if (DEBUG_LOADERS) {
- Log.d(TAG, "queryIntentActivities took "
- + (SystemClock.uptimeMillis()-qiaTime) + "ms");
- }
- if (apps == null) {
- return;
- }
- N = apps.size();
- if (DEBUG_LOADERS) {
- Log.d(TAG, "queryIntentActivities got " + N + " apps");
- }
- if (N == 0) {
- // There are no apps?!?
- return;
- }
- if (mBatchSize == 0) {
- batchSize = N;
- } else {
- batchSize = mBatchSize;
- }
+ mBgAllAppsList.clear();
+ final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- Collections.sort(apps,
- new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));
- if (DEBUG_LOADERS) {
- Log.d(TAG, "sort took "
- + (SystemClock.uptimeMillis()-sortTime) + "ms");
- }
- }
-
- final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+ final PackageManager packageManager = mContext.getPackageManager();
+ List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
- startIndex = i;
- for (int j=0; i<N && j<batchSize; j++) {
- // This builds the icon bitmaps.
- mBgAllAppsList.add(new ApplicationInfo(packageManager, apps.get(i),
- mIconCache, mLabelCache));
- i++;
- }
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "queryIntentActivities took "
+ + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+ }
+ if (apps == null) {
+ return;
+ }
+ int N = apps.size();
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "queryIntentActivities got " + N + " apps");
+ }
+ if (N == 0) {
+ // There are no apps?!?
+ return;
+ }
- final boolean first = i <= batchSize;
- final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- final ArrayList<ApplicationInfo> added = mBgAllAppsList.added;
- mBgAllAppsList.added = new ArrayList<ApplicationInfo>();
+ final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+ Collections.sort(apps,
+ new ShortcutNameComparator(packageManager, mLabelCache));
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "sort took "
+ + (SystemClock.uptimeMillis()-sortTime) + "ms");
+ }
- mHandler.post(new Runnable() {
- public void run() {
- final long t = SystemClock.uptimeMillis();
- if (callbacks != null) {
- if (first) {
- callbacks.bindAllApplications(added);
- } else {
- callbacks.bindAppsAdded(added);
- }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "bound " + added.size() + " apps in "
- + (SystemClock.uptimeMillis() - t) + "ms");
- }
- } else {
- Log.i(TAG, "not binding apps: no Launcher activity");
- }
- }
- });
+ for (ResolveInfo info : apps) {
+ // This builds the icon bitmaps.
+ mBgAllAppsList.add(new ApplicationInfo(packageManager, info,
+ mIconCache, mLabelCache));
+ }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "batch of " + (i-startIndex) + " icons processed in "
- + (SystemClock.uptimeMillis()-t2) + "ms");
- }
+ final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ final ArrayList<ApplicationInfo> added = mBgAllAppsList.added;
+ mBgAllAppsList.added = new ArrayList<ApplicationInfo>();
- if (mAllAppsLoadDelay > 0 && i < N) {
- try {
+ mHandler.post(new Runnable() {
+ public void run() {
+ final long t = SystemClock.uptimeMillis();
+ if (callbacks != null) {
+ callbacks.bindAllApplications(added);
if (DEBUG_LOADERS) {
- Log.d(TAG, "sleeping for " + mAllAppsLoadDelay + "ms");
+ Log.d(TAG, "bound " + added.size() + " apps in "
+ + (SystemClock.uptimeMillis() - t) + "ms");
}
- Thread.sleep(mAllAppsLoadDelay);
- } catch (InterruptedException exc) { }
+ } else {
+ Log.i(TAG, "not binding apps: no Launcher activity");
+ }
}
- }
+ });
if (DEBUG_LOADERS) {
Log.d(TAG, "cached all " + N + " apps in "
- + (SystemClock.uptimeMillis()-t) + "ms"
- + (mAllAppsLoadDelay > 0 ? " (including delay)" : ""));
+ + (SystemClock.uptimeMillis()-t) + "ms");
}
}
@@ -1959,25 +1910,24 @@ public class LauncherModel extends BroadcastReceiver {
final Context context = mApp;
final String[] packages = mPackages;
- final int N = packages.length;
switch (mOp) {
case OP_ADD:
- for (int i=0; i<N; i++) {
- if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
- mBgAllAppsList.addPackage(context, packages[i]);
+ for (String p : packages) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + p);
+ mBgAllAppsList.addPackage(context, p);
}
break;
case OP_UPDATE:
- for (int i=0; i<N; i++) {
- if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
- mBgAllAppsList.updatePackage(context, packages[i]);
+ for (String p : packages) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + p);
+ mBgAllAppsList.updatePackage(context, p);
}
break;
case OP_REMOVE:
case OP_UNAVAILABLE:
- for (int i=0; i<N; i++) {
- if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
- mBgAllAppsList.removePackage(packages[i]);
+ for (String p : packages) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + p);
+ mBgAllAppsList.removePackage(p);
}
break;
}
@@ -2000,9 +1950,7 @@ public class LauncherModel extends BroadcastReceiver {
if (mBgAllAppsList.removed.size() > 0) {
mBgAllAppsList.removed.clear();
- for (int i = 0; i < N; ++i) {
- removedPackageNames.add(packages[i]);
- }
+ removedPackageNames.addAll(Arrays.asList(packages));
}
final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
@@ -2016,7 +1964,7 @@ public class LauncherModel extends BroadcastReceiver {
mHandler.post(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (callbacks == cb && cb != null) {
+ if (callbacks == cb) {
callbacks.bindAppsAdded(addedFinal);
}
}
@@ -2027,7 +1975,7 @@ public class LauncherModel extends BroadcastReceiver {
mHandler.post(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (callbacks == cb && cb != null) {
+ if (callbacks == cb) {
callbacks.bindAppsUpdated(modifiedFinal);
}
}
@@ -2038,7 +1986,7 @@ public class LauncherModel extends BroadcastReceiver {
mHandler.post(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (callbacks == cb && cb != null) {
+ if (callbacks == cb) {
callbacks.bindAppsRemoved(removedPackageNames, permanent);
}
}
@@ -2049,7 +1997,7 @@ public class LauncherModel extends BroadcastReceiver {
@Override
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (callbacks == cb && cb != null) {
+ if (callbacks == cb) {
callbacks.bindPackagesUpdated();
}
}
@@ -2268,59 +2216,6 @@ public class LauncherModel extends BroadcastReceiver {
return info;
}
- /**
- * Attempts to find an AppWidgetProviderInfo that matches the given component.
- */
- AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,
- ComponentName component) {
- List<AppWidgetProviderInfo> widgets =
- AppWidgetManager.getInstance(context).getInstalledProviders();
- for (AppWidgetProviderInfo info : widgets) {
- if (info.provider.equals(component)) {
- return info;
- }
- }
- return null;
- }
-
- /**
- * Returns a list of all the widgets that can handle configuration with a particular mimeType.
- */
- List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {
- final PackageManager packageManager = context.getPackageManager();
- final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =
- new ArrayList<WidgetMimeTypeHandlerData>();
-
- final Intent supportsIntent =
- new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);
- supportsIntent.setType(mimeType);
-
- // Create a set of widget configuration components that we can test against
- final List<AppWidgetProviderInfo> widgets =
- AppWidgetManager.getInstance(context).getInstalledProviders();
- final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =
- new HashMap<ComponentName, AppWidgetProviderInfo>();
- for (AppWidgetProviderInfo info : widgets) {
- configurationComponentToWidget.put(info.configure, info);
- }
-
- // Run through each of the intents that can handle this type of clip data, and cross
- // reference them with the components that are actual configuration components
- final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,
- PackageManager.MATCH_DEFAULT_ONLY);
- for (ResolveInfo info : activities) {
- final ActivityInfo activityInfo = info.activityInfo;
- final ComponentName infoComponent = new ComponentName(activityInfo.packageName,
- activityInfo.name);
- if (configurationComponentToWidget.containsKey(infoComponent)) {
- supportedConfigurationActivities.add(
- new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,
- configurationComponentToWidget.get(infoComponent)));
- }
- }
- return supportedConfigurationActivities;
- }
-
ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
@@ -2454,7 +2349,7 @@ public class LauncherModel extends BroadcastReceiver {
final Collator collator = Collator.getInstance();
return new Comparator<AppWidgetProviderInfo>() {
public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
- return collator.compare(a.label.toString(), b.label.toString());
+ return collator.compare(a.label, b.label);
}
};
}
@@ -2499,7 +2394,7 @@ public class LauncherModel extends BroadcastReceiver {
}
return mCollator.compare(labelA, labelB);
}
- };
+ }
public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
private Collator mCollator;
private PackageManager mPackageManager;
@@ -2537,7 +2432,7 @@ public class LauncherModel extends BroadcastReceiver {
}
return mCollator.compare(labelA, labelB);
}
- };
+ }
public void dumpState() {
Log.d(TAG, "mCallbacks=" + mCallbacks);
diff --git a/src/com/cyanogenmod/trebuchet/LauncherProvider.java b/src/com/cyanogenmod/trebuchet/LauncherProvider.java
index 4e4c1b2..45ae99c 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherProvider.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherProvider.java
@@ -49,7 +49,6 @@ import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.LauncherSettings.Favorites;
import org.xmlpull.v1.XmlPullParser;
@@ -157,9 +156,8 @@ public class LauncherProvider extends ContentProvider {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
- int numValues = values.length;
- for (int i = 0; i < numValues; i++) {
- if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) {
+ for (ContentValues value : values) {
+ if (dbInsertAndCheck(mOpenHelper, db, args.table, null, value) < 0) {
return 0;
}
}
@@ -774,12 +772,12 @@ public class LauncherProvider extends ContentProvider {
}
}
- private static final void beginDocument(XmlPullParser parser, String firstElementName)
+ private static void beginDocument(XmlPullParser parser, String firstElementName)
throws XmlPullParserException, IOException {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
- ;
+
}
if (type != XmlPullParser.START_TAG) {
@@ -850,7 +848,7 @@ public class LauncherProvider extends ContentProvider {
} else if (TAG_CLOCK.equals(name)) {
added = addClockWidget(db, values);
} else if (TAG_APPWIDGET.equals(name)) {
- added = addAppWidget(parser, attrs, type, db, values, a, packageManager);
+ added = addAppWidget(parser, attrs, db, values, a, packageManager);
} else if (TAG_SHORTCUT.equals(name)) {
long id = addUriShortcut(db, values, a);
added = id >= 0;
@@ -990,9 +988,8 @@ public class LauncherProvider extends ContentProvider {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
List<AppWidgetProviderInfo> providers = appWidgetManager.getInstalledProviders();
if (providers == null) return null;
- final int providerCount = providers.size();
- for (int i = 0; i < providerCount; i++) {
- ComponentName provider = providers.get(i).provider;
+ for (AppWidgetProviderInfo p : providers) {
+ ComponentName provider = p.provider;
if (provider != null && provider.getPackageName().equals(packageName)) {
return provider;
}
@@ -1011,7 +1008,7 @@ public class LauncherProvider extends ContentProvider {
return addAppWidget(db, values, cn, 2, 2, null);
}
- private boolean addAppWidget(XmlResourceParser parser, AttributeSet attrs, int type,
+ private boolean addAppWidget(XmlResourceParser parser, AttributeSet attrs,
SQLiteDatabase db, ContentValues values, TypedArray a,
PackageManager packageManager) throws XmlPullParserException, IOException {
@@ -1044,6 +1041,7 @@ public class LauncherProvider extends ContentProvider {
// Read the extras
Bundle extras = new Bundle();
int widgetDepth = parser.getDepth();
+ int type;
while ((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > widgetDepth) {
if (type != XmlPullParser.START_TAG) {
diff --git a/src/com/cyanogenmod/trebuchet/PagedView.java b/src/com/cyanogenmod/trebuchet/PagedView.java
index a2b353f..0076b83 100644
--- a/src/com/cyanogenmod/trebuchet/PagedView.java
+++ b/src/com/cyanogenmod/trebuchet/PagedView.java
@@ -177,7 +177,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected boolean mUsePagingTouchSlop = true;
// If true, the subclass should directly update scrollX itself in its computeScroll method
- // (SmoothPagedView does this)
protected boolean mDeferScrollUpdate = false;
protected boolean mIsPageMoving = false;
@@ -461,7 +460,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
}
- // we moved this functionality to a helper function so SmoothPagedView can reuse it
protected boolean computeScrollHelper() {
if (mScroller.computeScrollOffset()) {
// Don't bother scrolling if the page does not need to be moved
@@ -1696,6 +1694,30 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
+ public static class OvershootInterpolator implements Interpolator {
+ private static final float DEFAULT_TENSION = 1.3f;
+ private float mTension;
+
+ public OvershootInterpolator() {
+ mTension = DEFAULT_TENSION;
+ }
+
+ public void setDistance(int distance) {
+ mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
+ }
+
+ public void disableSettle() {
+ mTension = 0.f;
+ }
+
+ public float getInterpolation(float t) {
+ // _o(t) = t * t * ((tension + 1) * t + tension)
+ // o(t) = _o(t - 1) + 1
+ t -= 1.0f;
+ return t * t * ((mTension + 1) * t + mTension) + 1.0f;
+ }
+ }
+
protected Interpolator getScrollInterpolator() {
return new QuintInterpolator();
}
diff --git a/src/com/cyanogenmod/trebuchet/ShortcutInfo.java b/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
index 3c1f985..0a8dbf9 100644
--- a/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
+++ b/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
@@ -17,6 +17,7 @@
package com.cyanogenmod.trebuchet;
import java.util.ArrayList;
+import java.util.Arrays;
import android.content.ComponentName;
import android.content.ContentValues;
@@ -169,7 +170,7 @@ class ShortcutInfo extends ItemInfo {
return "ShortcutInfo(title=" + title.toString() + "intent=" + intent + "id=" + this.id
+ " type=" + this.itemType + " container=" + this.container + " screen=" + screen
+ " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY
- + " dropPos=" + dropPos + ")";
+ + " dropPos=" + Arrays.toString(dropPos) + ")";
}
public static void dumpShortcutInfoList(String tag, String label,
diff --git a/src/com/cyanogenmod/trebuchet/SmoothPagedView.java b/src/com/cyanogenmod/trebuchet/SmoothPagedView.java
deleted file mode 100644
index 86caf9e..0000000
--- a/src/com/cyanogenmod/trebuchet/SmoothPagedView.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.cyanogenmod.trebuchet;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.animation.Interpolator;
-import android.widget.Scroller;
-
-public abstract class SmoothPagedView extends PagedView {
- private static final float SMOOTHING_SPEED = 0.75f;
- private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
-
- private float mBaseLineFlingVelocity;
- private float mFlingVelocityInfluence;
-
- static final int DEFAULT_MODE = 0;
- static final int X_LARGE_MODE = 1;
-
- int mScrollMode;
-
- private Interpolator mScrollInterpolator;
-
- public static class OvershootInterpolator implements Interpolator {
- private static final float DEFAULT_TENSION = 1.3f;
- private float mTension;
-
- public OvershootInterpolator() {
- mTension = DEFAULT_TENSION;
- }
-
- public void setDistance(int distance) {
- mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
- }
-
- public void disableSettle() {
- mTension = 0.f;
- }
-
- public float getInterpolation(float t) {
- // _o(t) = t * t * ((tension + 1) * t + tension)
- // o(t) = _o(t - 1) + 1
- t -= 1.0f;
- return t * t * ((mTension + 1) * t + mTension) + 1.0f;
- }
- }
-
- /**
- * Used to inflate the Workspace from XML.
- *
- * @param context The application's context.
- * @param attrs The attributes set containing the Workspace's customization values.
- */
- public SmoothPagedView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Used to inflate the Workspace from XML.
- *
- * @param context The application's context.
- * @param attrs The attributes set containing the Workspace's customization values.
- * @param defStyle Unused.
- */
- public SmoothPagedView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mUsePagingTouchSlop = false;
-
- // This means that we'll take care of updating the scroll parameter ourselves (we do it
- // in computeScroll), we only do this in the OVERSHOOT_MODE, ie. on phones
- mDeferScrollUpdate = mScrollMode != X_LARGE_MODE;
- }
-
- protected int getScrollMode() {
- return X_LARGE_MODE;
- }
-
- /**
- * Initializes various states for this workspace.
- */
- @Override
- protected void init() {
- super.init();
-
- mScrollMode = getScrollMode();
- if (mScrollMode == DEFAULT_MODE) {
- mBaseLineFlingVelocity = 2500.0f;
- mFlingVelocityInfluence = 0.4f;
- mScrollInterpolator = new OvershootInterpolator();
- mScroller = new Scroller(getContext(), mScrollInterpolator);
- }
- }
-
- @Override
- protected void snapToDestination() {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToDestination();
- } else {
- snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0);
- }
- }
-
- @Override
- protected void snapToPageWithVelocity(int whichPage, int velocity) {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToPageWithVelocity(whichPage, velocity);
- } else {
- snapToPageWithVelocity(whichPage, 0, true);
- }
- }
-
- private void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) {
- // if (!mScroller.isFinished()) return;
-
- whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
-
- final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
- final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
- final int delta = newX - mUnboundedScrollX;
- int duration = (screenDelta + 1) * 100;
-
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- if (settle) {
- ((OvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
- } else {
- ((OvershootInterpolator) mScrollInterpolator).disableSettle();
- }
-
- velocity = Math.abs(velocity);
- if (velocity > 0) {
- duration += (duration / (velocity / mBaseLineFlingVelocity)) * mFlingVelocityInfluence;
- } else {
- duration += 100;
- }
-
- snapToPage(whichPage, delta, duration);
- }
-
- @Override
- protected void snapToPage(int whichPage) {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToPage(whichPage);
- } else {
- snapToPageWithVelocity(whichPage, 0, false);
- }
- }
-
- @Override
- public void computeScroll() {
- if (mScrollMode == X_LARGE_MODE) {
- super.computeScroll();
- } else {
- boolean scrollComputed = computeScrollHelper();
-
- if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) {
- final float now = System.nanoTime() / NANOTIME_DIV;
- final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
-
- final float dx = mTouchX - mUnboundedScrollX;
- scrollTo(Math.round(mUnboundedScrollX + dx * e), getScrollY());
- mSmoothingTime = now;
-
- // Keep generating points as long as we're more than 1px away from the target
- if (dx > 1.f || dx < -1.f) {
- invalidate();
- }
- }
- }
- }
-}
diff --git a/src/com/cyanogenmod/trebuchet/StrokedTextView.java b/src/com/cyanogenmod/trebuchet/StrokedTextView.java
index 007ddf5..be2bd06 100644
--- a/src/com/cyanogenmod/trebuchet/StrokedTextView.java
+++ b/src/com/cyanogenmod/trebuchet/StrokedTextView.java
@@ -105,12 +105,12 @@ public class StrokedTextView extends TextView {
final int drawableLeft = getPaddingLeft();
final int drawableTop = getPaddingTop();
final Drawable[] drawables = getCompoundDrawables();
- for (int i = 0; i < drawables.length; ++i) {
- if (drawables[i] != null) {
- drawables[i].setBounds(drawableLeft, drawableTop,
- drawableLeft + drawables[i].getIntrinsicWidth(),
- drawableTop + drawables[i].getIntrinsicHeight());
- drawables[i].draw(mCanvas);
+ for (Drawable drawable : drawables) {
+ if (drawable != null) {
+ drawable.setBounds(drawableLeft, drawableTop,
+ drawableLeft + drawable.getIntrinsicWidth(),
+ drawableTop + drawable.getIntrinsicHeight());
+ drawable.draw(mCanvas);
}
}
diff --git a/src/com/cyanogenmod/trebuchet/SymmetricalLinearTween.java b/src/com/cyanogenmod/trebuchet/SymmetricalLinearTween.java
deleted file mode 100644
index 240305f..0000000
--- a/src/com/cyanogenmod/trebuchet/SymmetricalLinearTween.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.cyanogenmod.trebuchet;
-
-import android.os.Handler;
-import android.os.SystemClock;
-
-/**
- * Provides an animation between 0.0f and 1.0f over a given duration.
- */
-class SymmetricalLinearTween {
-
- private static final int FPS = 30;
- private static final int FRAME_TIME = 1000 / FPS;
-
- Handler mHandler;
- int mDuration;
- TweenCallback mCallback;
-
- boolean mRunning;
- long mBase;
- boolean mDirection;
- float mValue;
-
- /**
- * @param duration milliseconds duration
- * @param callback callbacks
- */
- public SymmetricalLinearTween(boolean initial, int duration, TweenCallback callback) {
- mValue = initial ? 1.0f : 0.0f;
- mDirection = initial;
- mDuration = duration;
- mCallback = callback;
- mHandler = new Handler();
- }
-
- /**
- * Starts the tweening.
- *
- * @param direction If direction is true, the value goes towards 1.0f. If direction
- * is false, the value goes towards 0.0f.
- */
- public void start(boolean direction) {
- start(direction, SystemClock.uptimeMillis());
- }
-
- /**
- * Starts the tweening.
- *
- * @param direction If direction is true, the value goes towards 1.0f. If direction
- * is false, the value goes towards 0.0f.
- * @param baseTime The time to use as zero for this animation, in the
- * {@link SystemClock.uptimeMillis} time base. This allows you to
- * synchronize multiple animations.
- */
- public void start(boolean direction, long baseTime) {
- if (direction != mDirection) {
- if (!mRunning) {
- mBase = baseTime;
- mRunning = true;
- mCallback.onTweenStarted();
- long next = SystemClock.uptimeMillis() + FRAME_TIME;
- mHandler.postAtTime(mTick, next);
- } else {
- // reverse direction
- long now = SystemClock.uptimeMillis();
- long diff = now - mBase;
- mBase = now + diff - mDuration;
- }
- mDirection = direction;
- }
- }
-
- Runnable mTick = new Runnable() {
- public void run() {
- long base = mBase;
- long now = SystemClock.uptimeMillis();
- long diff = now-base;
- int duration = mDuration;
- float val = diff/(float)duration;
- if (!mDirection) {
- val = 1.0f - val;
- }
- if (val > 1.0f) {
- val = 1.0f;
- } else if (val < 0.0f) {
- val = 0.0f;
- }
- float old = mValue;
- mValue = val;
- mCallback.onTweenValueChanged(val, old);
- int frame = (int)(diff / FRAME_TIME);
- long next = base + ((frame+1)*FRAME_TIME);
- if (diff < duration) {
- mHandler.postAtTime(this, next);
- }
- if (diff >= duration) {
- mCallback.onTweenFinished();
- mRunning = false;
- }
- }
- };
-}
-
diff --git a/src/com/cyanogenmod/trebuchet/TweenCallback.java b/src/com/cyanogenmod/trebuchet/TweenCallback.java
deleted file mode 100644
index 88b8dff..0000000
--- a/src/com/cyanogenmod/trebuchet/TweenCallback.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.cyanogenmod.trebuchet;
-
-interface TweenCallback {
- void onTweenValueChanged(float value, float oldValue);
- void onTweenStarted();
- void onTweenFinished();
-}
-
diff --git a/src/com/cyanogenmod/trebuchet/UninstallShortcutReceiver.java b/src/com/cyanogenmod/trebuchet/UninstallShortcutReceiver.java
index 6f4f030..6df068a 100644
--- a/src/com/cyanogenmod/trebuchet/UninstallShortcutReceiver.java
+++ b/src/com/cyanogenmod/trebuchet/UninstallShortcutReceiver.java
@@ -141,7 +141,7 @@ public class UninstallShortcutReceiver extends BroadcastReceiver {
newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
synchronized (newApps) {
do {
- appRemoved = newApps.remove(intent.toUri(0).toString());
+ appRemoved = newApps.remove(intent.toUri(0));
} while (appRemoved);
}
if (appRemoved) {
diff --git a/src/com/cyanogenmod/trebuchet/UserInitializeReceiver.java b/src/com/cyanogenmod/trebuchet/UserInitializeReceiver.java
index db20ae9..9bd11a1 100644
--- a/src/com/cyanogenmod/trebuchet/UserInitializeReceiver.java
+++ b/src/com/cyanogenmod/trebuchet/UserInitializeReceiver.java
@@ -51,6 +51,7 @@ public class UserInitializeReceiver extends BroadcastReceiver {
try {
wpm.setResource(resid);
} catch (IOException e) {
+ // Ignore
}
return;
}
diff --git a/src/com/cyanogenmod/trebuchet/Utilities.java b/src/com/cyanogenmod/trebuchet/Utilities.java
index 5dca18b..b9520b3 100644
--- a/src/com/cyanogenmod/trebuchet/Utilities.java
+++ b/src/com/cyanogenmod/trebuchet/Utilities.java
@@ -16,8 +16,6 @@
package com.cyanogenmod.trebuchet;
-import java.util.Random;
-
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -34,8 +32,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.util.DisplayMetrics;
-import com.cyanogenmod.trebuchet.R;
-
/**
* Various utilities shared amongst the Launcher's classes.
*/
@@ -249,27 +245,4 @@ final class Utilities {
sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm));
sDisabledPaint.setAlpha(0x88);
}
-
- /** Only works for positive numbers. */
- static int roundToPow2(int n) {
- int orig = n;
- n >>= 1;
- int mask = 0x8000000;
- while (mask != 0 && (n & mask) == 0) {
- mask >>= 1;
- }
- while (mask != 0) {
- n |= mask;
- mask >>= 1;
- }
- n += 1;
- if (n != orig) {
- n <<= 1;
- }
- return n;
- }
-
- static int generateRandomId() {
- return new Random(System.currentTimeMillis()).nextInt(1 << 24);
- }
}
diff --git a/src/com/cyanogenmod/trebuchet/WallpaperChooserDialogFragment.java b/src/com/cyanogenmod/trebuchet/WallpaperChooserDialogFragment.java
index 091bf50..b140a41 100644
--- a/src/com/cyanogenmod/trebuchet/WallpaperChooserDialogFragment.java
+++ b/src/com/cyanogenmod/trebuchet/WallpaperChooserDialogFragment.java
@@ -34,20 +34,18 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.BaseAdapter;
-import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;
-
-import com.cyanogenmod.trebuchet.R;
+import com.cyanogenmod.trebuchet.widget.CustomAdapterView;
+import com.cyanogenmod.trebuchet.widget.EcoGallery;
import java.io.IOException;
import java.util.ArrayList;
public class WallpaperChooserDialogFragment extends DialogFragment implements
- AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+ CustomAdapterView.OnItemSelectedListener, CustomAdapterView.OnItemClickListener {
private static final String TAG = "Trebuchet.WallpaperChooserDialogFragment";
private static final String EMBEDDED_KEY = "com.cyanogenmod.trebuchet."
@@ -139,7 +137,7 @@ public class WallpaperChooserDialogFragment extends DialogFragment implements
View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
view.setBackground(mWallpaperDrawable);
- final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+ final EcoGallery gallery = (EcoGallery) view.findViewById(R.id.gallery);
gallery.setCallbackDuringFling(false);
gallery.setOnItemSelectedListener(this);
gallery.setAdapter(new ImageAdapter(getActivity()));
@@ -171,13 +169,13 @@ public class WallpaperChooserDialogFragment extends DialogFragment implements
// Click handler for the Dialog's GridView
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ public void onItemClick(CustomAdapterView<?> parent, View view, int position, long id) {
selectWallpaper(position);
}
// Selection handler for the embedded Gallery view
@Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ public void onItemSelected(CustomAdapterView<?> parent, View view, int position, long id) {
if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
mLoader.cancel();
}
@@ -185,7 +183,7 @@ public class WallpaperChooserDialogFragment extends DialogFragment implements
}
@Override
- public void onNothingSelected(AdapterView<?> parent) {
+ public void onNothingSelected(CustomAdapterView<?> parent) {
}
private void findWallpapers() {
diff --git a/src/com/cyanogenmod/trebuchet/Workspace.java b/src/com/cyanogenmod/trebuchet/Workspace.java
index fa0c9ec..81854d8 100644
--- a/src/com/cyanogenmod/trebuchet/Workspace.java
+++ b/src/com/cyanogenmod/trebuchet/Workspace.java
@@ -44,7 +44,6 @@ import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -62,7 +61,6 @@ import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.TextView;
-import com.cyanogenmod.trebuchet.R;
import com.cyanogenmod.trebuchet.FolderIcon.FolderRingAnimator;
import com.cyanogenmod.trebuchet.LauncherSettings.Favorites;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
@@ -78,7 +76,7 @@ import java.util.Set;
* Each page contains a number of icons, folders or widgets the user can
* interact with. A workspace is meant to be used with a fixed width only.
*/
-public class Workspace extends SmoothPagedView
+public class Workspace extends PagedView
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener {
private static final String TAG = "Trebuchet.Workspace";
@@ -86,7 +84,6 @@ public class Workspace extends SmoothPagedView
// Y rotation to apply to the workspace screens
private static final float WORKSPACE_ROTATION = 12.5f;
private static final float WORKSPACE_OVERSCROLL_ROTATION = 24f;
- private static float CAMERA_DISTANCE = 6500;
private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
@@ -110,7 +107,6 @@ public class Workspace extends SmoothPagedView
private Drawable mBackground;
boolean mDrawBackground = true;
private float mBackgroundAlpha = 0;
- private float mOverScrollMaxBackgroundAlpha = 0.0f;
private float mWallpaperScrollRatio = 1.0f;
@@ -121,7 +117,6 @@ public class Workspace extends SmoothPagedView
private int[] mWallpaperOffsets = new int[2];
private Paint mPaint = new Paint();
private IBinder mWindowToken;
- private static final float DEFAULT_WALLPAPER_SCREENS_SPAN = 2f;
/**
* CellInfo for the cell that is currently being dragged
@@ -161,9 +156,7 @@ public class Workspace extends SmoothPagedView
private int[] mTempCell = new int[2];
private int[] mTempEstimate = new int[2];
private float[] mDragViewVisualCenter = new float[2];
- private float[] mTempDragCoordinates = new float[2];
private float[] mTempCellLayoutCenterCoordinates = new float[2];
- private float[] mTempDragBottomRightCoordinates = new float[2];
private Matrix mTempInverseMatrix = new Matrix();
private SpringLoadedDragController mSpringLoadedDragController;
@@ -175,7 +168,7 @@ public class Workspace extends SmoothPagedView
// State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
- enum State { NORMAL, SPRING_LOADED, SMALL };
+ enum State { NORMAL, SPRING_LOADED, SMALL }
private State mState = State.NORMAL;
private boolean mIsSwitchingState = false;
@@ -203,7 +196,6 @@ public class Workspace extends SmoothPagedView
private final Camera mCamera = new Camera();
private final float mTempFloat2[] = new float[2];
- enum WallpaperVerticalOffset { TOP, MIDDLE, BOTTOM };
int mWallpaperWidth;
int mWallpaperHeight;
WallpaperOffsetInterpolator mWallpaperInterpolator;
@@ -267,7 +259,6 @@ public class Workspace extends SmoothPagedView
private float[] mOldScaleXs;
private float[] mOldScaleYs;
private float[] mOldBackgroundAlphas;
- private float[] mOldBackgroundAlphaMultipliers;
private float[] mOldAlphas;
private float[] mOldRotations;
private float[] mOldRotationYs;
@@ -276,7 +267,6 @@ public class Workspace extends SmoothPagedView
private float[] mNewScaleXs;
private float[] mNewScaleYs;
private float[] mNewBackgroundAlphas;
- private float[] mNewBackgroundAlphaMultipliers;
private float[] mNewAlphas;
private float[] mNewRotations;
private float[] mNewRotationYs;
@@ -355,6 +345,8 @@ public class Workspace extends SmoothPagedView
mHandleFadeInAdjacentScreens = true;
mWallpaperManager = WallpaperManager.getInstance(context);
+ mUsePagingTouchSlop = false;
+
int cellCountX = DEFAULT_CELL_COUNT_X;
int cellCountY = DEFAULT_CELL_COUNT_Y;
@@ -456,11 +448,11 @@ public class Workspace extends SmoothPagedView
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
// dimension if unsuccessful
public int[] estimateItemSize(int hSpan, int vSpan,
- ItemInfo itemInfo, boolean springLoaded) {
+ boolean springLoaded) {
int[] size = new int[2];
if (getChildCount() > 0) {
CellLayout cl = (CellLayout) mLauncher.getWorkspace().getChildAt(0);
- Rect r = estimateItemPosition(cl, itemInfo, 0, 0, hSpan, vSpan);
+ Rect r = estimateItemPosition(cl, 0, 0, hSpan, vSpan);
size[0] = r.width();
size[1] = r.height();
if (springLoaded) {
@@ -474,8 +466,7 @@ public class Workspace extends SmoothPagedView
return size;
}
}
- public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
- int hCell, int vCell, int hSpan, int vSpan) {
+ public Rect estimateItemPosition(CellLayout cl, int hCell, int vCell, int hSpan, int vSpan) {
Rect r = new Rect();
cl.cellToRect(hCell, vCell, hSpan, vSpan, r);
return r;
@@ -507,7 +498,6 @@ public class Workspace extends SmoothPagedView
protected void initWorkspace() {
Context context = getContext();
mCurrentPage = mDefaultHomescreen;
- Launcher.setScreen(mCurrentPage);
LauncherApplication app = (LauncherApplication)context.getApplicationContext();
mIconCache = app.getIconCache();
setWillNotDraw(false);
@@ -576,11 +566,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected int getScrollMode() {
- return SmoothPagedView.X_LARGE_MODE;
- }
-
- @Override
public void onChildViewAdded(View parent, View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
@@ -659,6 +644,12 @@ public class Workspace extends SmoothPagedView
+ " (was " + screen + "); skipping child");
return;
}
+ } else if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ if (screen < 0 || screen >= mLauncher.getHotseat().getChildCount()) {
+ Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
+ + " (was " + screen + "); skipping child");
+ return;
+ }
}
final CellLayout layout;
@@ -668,11 +659,7 @@ public class Workspace extends SmoothPagedView
y = mLauncher.getHotseat().getCellYFromOrder(x);
x = mLauncher.getHotseat().getCellXFromOrder(x);
screen = mLauncher.getHotseat().getScreenFromOrder(screen);
- if (screen < 0 || screen >= mLauncher.getHotseat().getChildCount()) {
- layout = (CellLayout) mLauncher.getHotseat().getLayout();
- } else {
- layout = (CellLayout) mLauncher.getHotseat().getPageAt(screen);
- }
+ layout = (CellLayout) mLauncher.getHotseat().getPageAt(screen);
child.setOnKeyListener(null);
// Hide titles in the hotseat
@@ -718,7 +705,7 @@ public class Workspace extends SmoothPagedView
}
// Get the canonical child id to uniquely represent this view in this screen
- int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
+ int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y);
boolean markCellsAsOccupied = !(child instanceof Folder);
if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
// TODO: This branch occurs when the workspace is adding views
@@ -798,11 +785,7 @@ public class Workspace extends SmoothPagedView
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
- if (isSmall() || !isFinishedSwitchingState()) {
- // when the home screens are shrunken, shouldn't allow side-scrolling
- return false;
- }
- return super.dispatchUnhandledMove(focused, direction);
+ return !isSmall() && isFinishedSwitchingState() && super.dispatchUnhandledMove(focused, direction);
}
@Override
@@ -948,7 +931,6 @@ public class Workspace extends SmoothPagedView
hideScrollingIndicator(false);
}
}
- mOverScrollMaxBackgroundAlpha = 0.0f;
if (mDelayedResizeRunnable != null) {
mDelayedResizeRunnable.run();
@@ -969,12 +951,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected void notifyPageSwitchListener() {
- super.notifyPageSwitchListener();
- Launcher.setScreen(mCurrentPage);
- };
-
- @Override
protected int getScrollingIndicatorId() {
switch (mScrollingIndicatorPosition) {
case SCROLLING_INDICATOR_TOP:
@@ -1043,7 +1019,7 @@ public class Workspace extends SmoothPagedView
mWallpaperHeight = maxDim;
} else {
int screens = mWallpaperSize;
- mWallpaperWidth = Math.max((int) (minDim * screens), maxDim);
+ mWallpaperWidth = Math.max(minDim * screens, maxDim);
mWallpaperHeight = maxDim;
}
new Thread("setWallpaperDimension") {
@@ -1341,7 +1317,7 @@ public class Workspace extends SmoothPagedView
mBackgroundFadeOutAnimation = LauncherAnimUtils.ofFloat(startAlpha, finalAlpha);
mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
- setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
+ setBackgroundAlpha((Float) animation.getAnimatedValue());
}
});
mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
@@ -1401,18 +1377,6 @@ public class Workspace extends SmoothPagedView
}
}
- float overScrollBackgroundAlphaInterpolator(float r) {
- float threshold = 0.08f;
-
- if (r > mOverScrollMaxBackgroundAlpha) {
- mOverScrollMaxBackgroundAlpha = r;
- } else if (r < mOverScrollMaxBackgroundAlpha) {
- r = mOverScrollMaxBackgroundAlpha;
- }
-
- return Math.min(r / threshold, 1.0f);
- }
-
private void setChildrenBackgroundAlphaMultipliers(float a) {
for (int i = 0; i < getChildCount(); i++) {
CellLayout child = (CellLayout) getChildAt(i);
@@ -2075,7 +2039,7 @@ public class Workspace extends SmoothPagedView
public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, boolean clipAlpha) {
final Canvas canvas = new Canvas();
- int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
+ int[] size = estimateItemSize(info.spanX, info.spanY, false);
// The outline is used to visualize where the item will land if dropped
mDragOutline = createDragOutline(b, canvas, DRAG_BITMAP_PADDING, size[0],
@@ -2095,7 +2059,6 @@ public class Workspace extends SmoothPagedView
mOldScaleXs = new float[childCount];
mOldScaleYs = new float[childCount];
mOldBackgroundAlphas = new float[childCount];
- mOldBackgroundAlphaMultipliers = new float[childCount];
mOldAlphas = new float[childCount];
mOldRotations = new float[childCount];
mOldRotationYs = new float[childCount];
@@ -2104,7 +2067,6 @@ public class Workspace extends SmoothPagedView
mNewScaleXs = new float[childCount];
mNewScaleYs = new float[childCount];
mNewBackgroundAlphas = new float[childCount];
- mNewBackgroundAlphaMultipliers = new float[childCount];
mNewAlphas = new float[childCount];
mNewRotations = new float[childCount];
mNewRotationYs = new float[childCount];
@@ -2165,8 +2127,7 @@ public class Workspace extends SmoothPagedView
float scale = finalScaleFactor;
float finalAlpha = (!mFadeInAdjacentScreens || stateIsSpringLoaded ||
(i == mCurrentPage)) ? 1f : 0f;
- float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
- float initialAlpha = currentAlpha;
+ float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
// Tablet effect
if (mTransitionEffect == TransitionEffect.Tablet || stateIsSmall || stateIsSpringLoaded) {
@@ -2600,8 +2561,8 @@ public class Workspace extends SmoothPagedView
}
void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, int screen,
- int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
- View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
+ boolean insertAtFirst, int intersectX, int intersectY) {
+ View view = mLauncher.createShortcut(R.layout.application, target, info);
final int[] cellXY = new int[2];
target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
@@ -2637,8 +2598,8 @@ public class Workspace extends SmoothPagedView
mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);
}
- int spanX = 1;
- int spanY = 1;
+ int spanX;
+ int spanY;
if (mDragInfo != null) {
final CellLayout.CellInfo dragCellInfo = mDragInfo;
spanX = dragCellInfo.spanX;
@@ -2714,7 +2675,7 @@ public class Workspace extends SmoothPagedView
return (aboveShortcut && willBecomeShortcut);
}
- boolean willAddToExistingUserFolder(Object dragInfo, CellLayout target, int[] targetCell,
+ boolean willAddToExistingUserFolder(ItemInfo dragInfo, CellLayout target, int[] targetCell,
float distance) {
if (distance > mMaxDistanceForFolderCreation) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
@@ -2791,7 +2752,7 @@ public class Workspace extends SmoothPagedView
return false;
}
- boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] targetCell,
+ boolean addToExistingFolderIfNecessary(CellLayout target, int[] targetCell,
float distance, DragObject d, boolean external) {
if (distance > mMaxDistanceForFolderCreation) return false;
@@ -2801,7 +2762,7 @@ public class Workspace extends SmoothPagedView
if (dropOverView instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) dropOverView;
- if (fi.acceptDrop(d.dragInfo)) {
+ if (fi.acceptDrop((ItemInfo)d.dragInfo)) {
fi.onDrop(d);
// if the drag started here, we need to remove it from the workspace
@@ -2867,7 +2828,7 @@ public class Workspace extends SmoothPagedView
return;
}
- if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
+ if (addToExistingFolderIfNecessary(dropTargetLayout, mTargetCell,
distance, d, false)) {
return;
}
@@ -2922,7 +2883,7 @@ public class Workspace extends SmoothPagedView
lp.cellVSpan = item.spanY;
lp.isLockedToGrid = true;
cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
- mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
+ mTargetCell[0], mTargetCell[1]));
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
cell instanceof LauncherAppWidgetHostView) {
@@ -3021,19 +2982,6 @@ public class Workspace extends SmoothPagedView
}
}
- public void getViewLocationRelativeToSelf(View v, int[] location) {
- getLocationInWindow(location);
- int x = location[0];
- int y = location[1];
-
- v.getLocationInWindow(location);
- int vX = location[0];
- int vY = location[1];
-
- location[0] = vX - x;
- location[1] = vY - y;
- }
-
public void onDragEnter(DragObject d) {
mDragEnforcer.onDragEnter();
mCreateUserFolderOnDrop = false;
@@ -3188,7 +3136,7 @@ public class Workspace extends SmoothPagedView
private void cleanupAddToFolder() {
if (mDragOverFolderIcon != null) {
- mDragOverFolderIcon.onDragExit(null);
+ mDragOverFolderIcon.onDragExit();
mDragOverFolderIcon = null;
}
}
@@ -3272,45 +3220,6 @@ public class Workspace extends SmoothPagedView
/*
*
- * Returns true if the passed CellLayout cl overlaps with dragView
- *
- */
- boolean overlaps(CellLayout cl, DragView dragView,
- int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
- // Transform the coordinates of the item being dragged to the CellLayout's coordinates
- final float[] draggedItemTopLeft = mTempDragCoordinates;
- draggedItemTopLeft[0] = dragViewX;
- draggedItemTopLeft[1] = dragViewY;
- final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
- draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getDragRegionWidth();
- draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getDragRegionHeight();
-
- // Transform the dragged item's top left coordinates
- // to the CellLayout's local coordinates
- mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
- float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
- float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
-
- if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
- // Transform the dragged item's bottom right coordinates
- // to the CellLayout's local coordinates
- mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
- float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
- float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
-
- if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
- float overlap = (overlapRegionRight - overlapRegionLeft) *
- (overlapRegionBottom - overlapRegionTop);
- if (overlap > 0) {
- return true;
- }
- }
- }
- return false;
- }
-
- /*
- *
* This method returns the CellLayout that is currently being dragged to. In order to drag
* to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
* strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
@@ -3318,8 +3227,7 @@ public class Workspace extends SmoothPagedView
* Return null if no CellLayout is currently being dragged over
*
*/
- private CellLayout findMatchingPageForDragOver(
- DragView dragView, float originX, float originY, boolean exact) {
+ private CellLayout findMatchingPageForDragOver(float originX, float originY, boolean exact) {
// We loop through all the screens (ie CellLayouts) and see which ones overlap
// with the item being dragged and then choose the one that's closest to the touch point
final int screenCount = getChildCount();
@@ -3426,7 +3334,7 @@ public class Workspace extends SmoothPagedView
}
}
if (layout == null) {
- layout = findMatchingPageForDragOver(d.dragView, d.x, d.y, false);
+ layout = findMatchingPageForDragOver(d.x, d.y, false);
}
if (layout != mDragTargetLayout) {
@@ -3554,8 +3462,6 @@ public class Workspace extends SmoothPagedView
if (mDragMode == DRAG_MODE_CREATE_FOLDER && !userFolderPending) {
setDragMode(DRAG_MODE_NONE);
}
-
- return;
}
class FolderCreationAlarmListener implements OnAlarmListener {
@@ -3637,7 +3543,7 @@ public class Workspace extends SmoothPagedView
*/
public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
- onDropExternal(dragInfo.dropPos, (ItemInfo) dragInfo, (CellLayout) layout, false);
+ onDropExternal(dragInfo.dropPos, dragInfo, layout, false);
return true;
}
mLauncher.showOutOfSpaceMessage(mLauncher.isHotseatLayout(layout));
@@ -3690,7 +3596,7 @@ public class Workspace extends SmoothPagedView
boolean findNearestVacantCell = true;
if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
- mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+ mTargetCell = findNearestArea(touchXY[0], touchXY[1], spanX, spanY,
cellLayout, mTargetCell);
float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0],
mDragViewVisualCenter[1], mTargetCell);
@@ -3768,7 +3674,7 @@ public class Workspace extends SmoothPagedView
animationStyle, finalView, true);
} else {
// This is for other drag/drop cases, like dragging from All Apps
- View view = null;
+ View view;
switch (info.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -3782,7 +3688,7 @@ public class Workspace extends SmoothPagedView
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
- (FolderInfo) info, mIconCache);
+ (FolderInfo) info);
if (mHideIconLabels) {
((FolderIcon) view).setTextVisible(false);
}
@@ -3794,7 +3700,7 @@ public class Workspace extends SmoothPagedView
// First we find the cell nearest to point at which the item is
// dropped, without any consideration to whether there is an item there.
if (touchXY != null) {
- mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+ mTargetCell = findNearestArea(touchXY[0], touchXY[1], spanX, spanY,
cellLayout, mTargetCell);
float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0],
mDragViewVisualCenter[1], mTargetCell);
@@ -3803,7 +3709,7 @@ public class Workspace extends SmoothPagedView
true, d.dragView, d.postAnimationRunnable)) {
return;
}
- if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, distance, d,
+ if (addToExistingFolderIfNecessary(cellLayout, mTargetCell, distance, d,
true)) {
return;
}
@@ -3841,7 +3747,7 @@ public class Workspace extends SmoothPagedView
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo.spanX,
- widgetInfo.spanY, widgetInfo, false);
+ widgetInfo.spanY, false);
int visibility = layout.getVisibility();
layout.setVisibility(VISIBLE);
@@ -3867,7 +3773,7 @@ public class Workspace extends SmoothPagedView
int spanX = info.spanX;
int spanY = info.spanY;
- Rect r = estimateItemPosition(layout, info, targetCell[0], targetCell[1], spanX, spanY);
+ Rect r = estimateItemPosition(layout, targetCell[0], targetCell[1], spanX, spanY);
loc[0] = r.left;
loc[1] = r.top;
@@ -3932,7 +3838,7 @@ public class Workspace extends SmoothPagedView
if (animationType == ANIMATE_INTO_POSITION_AND_REMAIN) {
endStyle = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
} else {
- endStyle = DragLayer.ANIMATION_END_DISAPPEAR;;
+ endStyle = DragLayer.ANIMATION_END_DISAPPEAR;
}
Runnable onComplete = new Runnable() {
@@ -3991,16 +3897,6 @@ public class Workspace extends SmoothPagedView
}
/**
- * Return the current CellInfo describing our current drag; this method exists
- * so that Launcher can sync this object with the correct info when the activity is created/
- * destroyed
- *
- */
- public CellLayout.CellInfo getDragInfo() {
- return mDragInfo;
- }
-
- /**
* Calculate the nearest cell where the given object would be dropped.
*
* pixelX and pixelY should be in the coordinate system of layout
@@ -4048,9 +3944,9 @@ public class Workspace extends SmoothPagedView
cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
}
cellLayout.onDropChild(mDragInfo.cell);
- }
- if (mDragInfo.cell != null) {
- mDragInfo.cell.setVisibility(VISIBLE);
+ if (mDragInfo.cell != null) {
+ mDragInfo.cell.setVisibility(VISIBLE);
+ }
}
mDragOutline = null;
mDragInfo = null;
@@ -4102,12 +3998,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected void onRestoreInstanceState(Parcelable state) {
- super.onRestoreInstanceState(state);
- Launcher.setScreen(mCurrentPage);
- }
-
- @Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
// We don't dispatch restoreInstanceState to our children using this code path.
// Some pages will be restored immediately as their items are bound immediately, and
@@ -4346,8 +4236,7 @@ public class Workspace extends SmoothPagedView
final ArrayList<ShortcutInfo> appsToRemoveFromFolder =
new ArrayList<ShortcutInfo>();
- for (int k = 0; k < contentsCount; k++) {
- final ShortcutInfo appInfo = contents.get(k);
+ for (final ShortcutInfo appInfo : contents) {
final Intent intent = appInfo.intent;
final ComponentName name = intent.getComponent();
@@ -4423,7 +4312,9 @@ public class Workspace extends SmoothPagedView
for (ItemInfo info : shortcuts) {
LauncherModel.deleteItemFromDatabase(context, info);
}
- } catch (URISyntaxException e) {}
+ } catch (URISyntaxException e) {
+ // Ignore
+ }
}
}
}
@@ -4447,9 +4338,7 @@ public class Workspace extends SmoothPagedView
final ComponentName name = intent.getComponent();
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
- final int appCount = apps.size();
- for (int k = 0; k < appCount; k++) {
- ApplicationInfo app = apps.get(k);
+ for (ApplicationInfo app : apps) {
if (app.componentName.equals(name)) {
BubbleTextView shortcut = (BubbleTextView) view;
info.updateIcon(mIconCache);
diff --git a/src/com/cyanogenmod/trebuchet/preference/DoubleNumberPickerPreference.java b/src/com/cyanogenmod/trebuchet/preference/DoubleNumberPickerPreference.java
index 1a38639..81b766a 100644
--- a/src/com/cyanogenmod/trebuchet/preference/DoubleNumberPickerPreference.java
+++ b/src/com/cyanogenmod/trebuchet/preference/DoubleNumberPickerPreference.java
@@ -160,7 +160,7 @@ public class DoubleNumberPickerPreference extends DialogPreference {
@Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
- persistString(mNumberPicker1.getValue() + "|" + mNumberPicker2.getValue());;
+ persistString(mNumberPicker1.getValue() + "|" + mNumberPicker2.getValue());
}
}
diff --git a/src/com/cyanogenmod/trebuchet/preference/HiddenAppsActivity.java b/src/com/cyanogenmod/trebuchet/preference/HiddenAppsActivity.java
index 6eef205..05aea7f 100644
--- a/src/com/cyanogenmod/trebuchet/preference/HiddenAppsActivity.java
+++ b/src/com/cyanogenmod/trebuchet/preference/HiddenAppsActivity.java
@@ -110,7 +110,7 @@ public class HiddenAppsActivity extends ListActivity implements MenuItem.OnMenuI
}
private void restore() {
- List<ComponentName> apps = new ArrayList();
+ List<ComponentName> apps = new ArrayList<ComponentName>();
String[] flattened = PreferenceManager.getDefaultSharedPreferences(this)
.getString("ui_drawer_hidden_apps", "").split("\\|");
for (String flat : flattened) {
diff --git a/src/com/cyanogenmod/trebuchet/preference/PreferencesProvider.java b/src/com/cyanogenmod/trebuchet/preference/PreferencesProvider.java
index 98cfd1a..8d747ce 100644
--- a/src/com/cyanogenmod/trebuchet/preference/PreferencesProvider.java
+++ b/src/com/cyanogenmod/trebuchet/preference/PreferencesProvider.java
@@ -69,7 +69,7 @@ public final class PreferencesProvider {
}
}
public static int getCellCountY(int def) {
- String[] values = getString("ui_homescreen_grid", def + "|0").split("\\|");;
+ String[] values = getString("ui_homescreen_grid", def + "|0").split("\\|");
try {
return Integer.parseInt(values[0]);
} catch (NumberFormatException e) {
diff --git a/src/com/cyanogenmod/trebuchet/widget/CustomAbsSpinner.java b/src/com/cyanogenmod/trebuchet/widget/CustomAbsSpinner.java
new file mode 100644
index 0000000..7861f50
--- /dev/null
+++ b/src/com/cyanogenmod/trebuchet/widget/CustomAbsSpinner.java
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.trebuchet.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Interpolator;
+import android.widget.ArrayAdapter;
+import android.widget.SpinnerAdapter;
+import com.cyanogenmod.trebuchet.R;
+
+public abstract class CustomAbsSpinner extends CustomAdapterView<SpinnerAdapter> {
+
+ SpinnerAdapter mAdapter;
+
+ int mHeightMeasureSpec;
+ int mWidthMeasureSpec;
+ boolean mBlockLayoutRequests;
+ int mSelectionLeftPadding = 0;
+ int mSelectionTopPadding = 0;
+ int mSelectionRightPadding = 0;
+ int mSelectionBottomPadding = 0;
+ Rect mSpinnerPadding = new Rect();
+ View mSelectedView = null;
+ Interpolator mInterpolator;
+
+ RecycleBin mRecycler = new RecycleBin();
+ private DataSetObserver mDataSetObserver;
+
+
+ /** Temporary frame to hold a child View's frame rectangle */
+ private Rect mTouchFrame;
+
+ public CustomAbsSpinner(Context context) {
+ super(context);
+ initAbsSpinner();
+ }
+
+ public CustomAbsSpinner(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CustomAbsSpinner(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initAbsSpinner();
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.CustomAbsSpinner, defStyle, 0);
+
+ CharSequence[] entries = a.getTextArray(R.styleable.CustomAbsSpinner_entries);
+ if (entries != null) {
+ ArrayAdapter<CharSequence> adapter =
+ new ArrayAdapter<CharSequence>(context,
+ android.R.layout.simple_spinner_item, entries);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ setAdapter(adapter);
+ }
+
+ a.recycle();
+ }
+
+ /**
+ * Common code for different constructor flavors
+ */
+ private void initAbsSpinner() {
+ setFocusable(true);
+ setWillNotDraw(false);
+ }
+
+
+ /**
+ * The Adapter is used to provide the data which backs this Spinner.
+ * It also provides methods to transform spinner items based on their position
+ * relative to the selected item.
+ * @param adapter The SpinnerAdapter to use for this Spinner
+ */
+ @Override
+ public void setAdapter(SpinnerAdapter adapter) {
+ if (null != mAdapter) {
+ mAdapter.unregisterDataSetObserver(mDataSetObserver);
+ resetList();
+ }
+
+ mAdapter = adapter;
+
+ mOldSelectedPosition = INVALID_POSITION;
+ mOldSelectedRowId = INVALID_ROW_ID;
+
+ if (mAdapter != null) {
+ mOldItemCount = mItemCount;
+ mItemCount = mAdapter.getCount();
+ checkFocus();
+
+ mDataSetObserver = new AdapterDataSetObserver();
+ mAdapter.registerDataSetObserver(mDataSetObserver);
+
+ int position = mItemCount > 0 ? 0 : INVALID_POSITION;
+
+ setSelectedPositionInt(position);
+ setNextSelectedPositionInt(position);
+
+ if (mItemCount == 0) {
+ // Nothing selected
+ checkSelectionChanged();
+ }
+
+ } else {
+ checkFocus();
+ resetList();
+ // Nothing selected
+ checkSelectionChanged();
+ }
+
+ requestLayout();
+ }
+
+ /**
+ * Clear out all children from the list
+ */
+ void resetList() {
+ mDataChanged = false;
+ mNeedSync = false;
+
+ removeAllViewsInLayout();
+ mOldSelectedPosition = INVALID_POSITION;
+ mOldSelectedRowId = INVALID_ROW_ID;
+
+ setSelectedPositionInt(INVALID_POSITION);
+ setNextSelectedPositionInt(INVALID_POSITION);
+ invalidate();
+ }
+
+ /**
+ * @see android.view.View#measure(int, int)
+ *
+ * Figure out the dimensions of this Spinner. The width comes from
+ * the widthMeasureSpec as Spinnners can't have their width set to
+ * UNSPECIFIED. The height is based on the height of the selected item
+ * plus padding.
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int widthSize;
+ int heightSize;
+
+ int paddingLeft = getPaddingLeft();
+ int paddingRight = getPaddingRight();
+ int paddingTop = getPaddingTop();
+ int paddingBottom = getPaddingBottom();
+
+ mSpinnerPadding.left = paddingLeft > mSelectionLeftPadding ? paddingLeft
+ : mSelectionLeftPadding;
+ mSpinnerPadding.top = paddingTop > mSelectionTopPadding ? paddingTop
+ : mSelectionTopPadding;
+ mSpinnerPadding.right = paddingRight > mSelectionRightPadding ? paddingRight
+ : mSelectionRightPadding;
+ mSpinnerPadding.bottom = paddingBottom > mSelectionBottomPadding ? paddingBottom
+ : mSelectionBottomPadding;
+
+ if (mDataChanged) {
+ handleDataChanged();
+ }
+
+ int preferredHeight = 0;
+ int preferredWidth = 0;
+ boolean needsMeasuring = true;
+
+ int selectedPosition = getSelectedItemPosition();
+ if (selectedPosition >= 0 && mAdapter != null) {
+ // Try looking in the recycler. (Maybe we were measured once already)
+ View view = mRecycler.get();
+ if (view == null) {
+ // Make a new one
+ view = mAdapter.getView(selectedPosition, null, this);
+ }
+
+ if (view != null) {
+ // Put in recycler for re-measuring and/or layout
+ mRecycler.add(selectedPosition, view);
+ }
+
+ if (view != null) {
+ if (view.getLayoutParams() == null) {
+ mBlockLayoutRequests = true;
+ view.setLayoutParams(generateDefaultLayoutParams());
+ mBlockLayoutRequests = false;
+ }
+ measureChild(view, widthMeasureSpec, heightMeasureSpec);
+
+ preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom;
+ preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right;
+
+ needsMeasuring = false;
+ }
+ }
+
+ if (needsMeasuring) {
+ // No views -- just use padding
+ preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom;
+ if (widthMode == MeasureSpec.UNSPECIFIED) {
+ preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right;
+ }
+ }
+
+ preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight());
+ preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth());
+
+ heightSize = resolveSize(preferredHeight, heightMeasureSpec);
+ widthSize = resolveSize(preferredWidth, widthMeasureSpec);
+
+ setMeasuredDimension(widthSize, heightSize);
+ mHeightMeasureSpec = heightMeasureSpec;
+ mWidthMeasureSpec = widthMeasureSpec;
+ }
+
+
+ int getChildHeight(View child) {
+ return child.getMeasuredHeight();
+ }
+
+ int getChildWidth(View child) {
+ return child.getMeasuredWidth();
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ void recycleAllViews() {
+ int childCount = getChildCount();
+ final CustomAbsSpinner.RecycleBin recycleBin = mRecycler;
+
+ // All views go in recycler
+ for (int i=0; i<childCount; i++) {
+ View v = getChildAt(i);
+ int index = mFirstPosition + i;
+ recycleBin.put(index, v);
+ }
+ }
+
+ @Override
+ void handleDataChanged() {
+ // FIXME -- this is called from both measure and layout.
+ // This is harmless right now, but we don't want to do redundant work if
+ // this gets more complicated
+ super.handleDataChanged();
+ }
+
+
+
+ /**
+ * Jump directly to a specific item in the adapter data.
+ */
+ public void setSelection(int position, boolean animate) {
+ // Animate only if requested position is already on screen somewhere
+ boolean shouldAnimate = animate && mFirstPosition <= position &&
+ position <= mFirstPosition + getChildCount() - 1;
+ setSelectionInt(position, shouldAnimate);
+ }
+
+
+ @Override
+ public void setSelection(int position) {
+ setNextSelectedPositionInt(position);
+ requestLayout();
+ invalidate();
+ }
+
+
+ /**
+ * Makes the item at the supplied position selected.
+ *
+ * @param position Position to select
+ * @param animate Should the transition be animated
+ *
+ */
+ void setSelectionInt(int position, boolean animate) {
+ if (position != mOldSelectedPosition) {
+ mBlockLayoutRequests = true;
+ int delta = position - mSelectedPosition;
+ setNextSelectedPositionInt(position);
+ layout(delta, animate);
+ mBlockLayoutRequests = false;
+ }
+ }
+
+ abstract void layout(int delta, boolean animate);
+
+ @Override
+ public View getSelectedView() {
+ if (mItemCount > 0 && mSelectedPosition >= 0) {
+ return getChildAt(mSelectedPosition - mFirstPosition);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Override to prevent spamming ourselves with layout requests
+ * as we place views
+ *
+ * @see android.view.View#requestLayout()
+ */
+ @Override
+ public void requestLayout() {
+ if (!mBlockLayoutRequests) {
+ super.requestLayout();
+ }
+ }
+
+
+
+ @Override
+ public SpinnerAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ @Override
+ public int getCount() {
+ return mItemCount;
+ }
+
+ /**
+ * Maps a point to a position in the list.
+ *
+ * @param x X in local coordinate
+ * @param y Y in local coordinate
+ * @return The position of the item which contains the specified point, or
+ * {@link #INVALID_POSITION} if the point does not intersect an item.
+ */
+ public int pointToPosition(int x, int y) {
+ Rect frame = mTouchFrame;
+ if (frame == null) {
+ mTouchFrame = new Rect();
+ frame = mTouchFrame;
+ }
+
+ final int count = getChildCount();
+ for (int i = count - 1; i >= 0; i--) {
+ View child = getChildAt(i);
+ if (child.getVisibility() == View.VISIBLE) {
+ child.getHitRect(frame);
+ if (frame.contains(x, y)) {
+ return mFirstPosition + i;
+ }
+ }
+ }
+ return INVALID_POSITION;
+ }
+
+ static class SavedState extends BaseSavedState {
+ long selectedId;
+ int position;
+
+ /**
+ * Constructor called from {@link CustomAbsSpinner#onSaveInstanceState()}
+ */
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ selectedId = in.readLong();
+ position = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeLong(selectedId);
+ out.writeInt(position);
+ }
+
+ @Override
+ public String toString() {
+ return "AbsSpinner.SavedState{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " selectedId=" + selectedId
+ + " position=" + position + "}";
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ SavedState ss = new SavedState(superState);
+ ss.selectedId = getSelectedItemId();
+ if (ss.selectedId >= 0) {
+ ss.position = getSelectedItemPosition();
+ } else {
+ ss.position = INVALID_POSITION;
+ }
+ return ss;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+
+ super.onRestoreInstanceState(ss.getSuperState());
+
+ if (ss.selectedId >= 0) {
+ mDataChanged = true;
+ mNeedSync = true;
+ mSyncRowId = ss.selectedId;
+ mSyncPosition = ss.position;
+ mSyncMode = SYNC_SELECTED_POSITION;
+ requestLayout();
+ }
+ }
+
+ class RecycleBin {
+ private SparseArray<View> mScrapHeap = new SparseArray<View>();
+
+ public void put(int position, View v) {
+ mScrapHeap.put(position, v);
+ }
+
+ public void add(int position, View v) {
+ mScrapHeap.put(mScrapHeap.size(), v);
+ }
+ public View get() {
+ if (mScrapHeap.size() < 1) return null;
+
+ View result = mScrapHeap.valueAt(0);
+ int key = mScrapHeap.keyAt(0);
+
+ if (result != null) {
+ mScrapHeap.delete(key);
+ }
+ return result;
+ }
+
+ View get(int position) {
+ // System.out.print("Looking for " + position);
+ View result = mScrapHeap.get(position);
+ if (result != null) {
+ // System.out.println(" HIT");
+ mScrapHeap.delete(position);
+ } else {
+ // System.out.println(" MISS");
+ }
+ return result;
+ }
+
+ View peek(int position) {
+ // System.out.print("Looking for " + position);
+ return mScrapHeap.get(position);
+ }
+
+ void clear() {
+ final SparseArray<View> scrapHeap = mScrapHeap;
+
+ final int count = scrapHeap.size();
+ for (int i = 0; i < count; i++) {
+ final View view = scrapHeap.valueAt(i);
+ if (view != null) {
+ removeDetachedView(view, true);
+ }
+ }
+
+ scrapHeap.clear();
+ }
+ }
+}
diff --git a/src/com/cyanogenmod/trebuchet/widget/CustomAdapterView.java b/src/com/cyanogenmod/trebuchet/widget/CustomAdapterView.java
new file mode 100644
index 0000000..fd3e8f5
--- /dev/null
+++ b/src/com/cyanogenmod/trebuchet/widget/CustomAdapterView.java
@@ -0,0 +1,1130 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.trebuchet.widget;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.ContextMenu;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.Adapter;
+import android.widget.ListView;
+
+public abstract class CustomAdapterView<T extends Adapter> extends ViewGroup {
+
+ /**
+ * The item view type returned by {@link Adapter#getItemViewType(int)} when
+ * the adapter does not want the item's view recycled.
+ */
+ public static final int ITEM_VIEW_TYPE_IGNORE = -1;
+
+ /**
+ * The item view type returned by {@link Adapter#getItemViewType(int)} when
+ * the item is a header or footer.
+ */
+ public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2;
+
+ /**
+ * The position of the first child displayed
+ */
+ int mFirstPosition = 0;
+
+ /**
+ * The offset in pixels from the top of the AdapterView to the top
+ * of the view to select during the next layout.
+ */
+ int mSpecificTop;
+
+ /**
+ * Position from which to start looking for mSyncRowId
+ */
+ int mSyncPosition;
+
+ /**
+ * Row id to look for when data has changed
+ */
+ long mSyncRowId = INVALID_ROW_ID;
+
+ /**
+ * Height of the view when mSyncPosition and mSyncRowId where set
+ */
+ long mSyncHeight;
+
+ /**
+ * True if we need to sync to mSyncRowId
+ */
+ boolean mNeedSync = false;
+
+ /**
+ * Indicates whether to sync based on the selection or position. Possible
+ * values are {@link #SYNC_SELECTED_POSITION} or
+ * {@link #SYNC_FIRST_POSITION}.
+ */
+ int mSyncMode;
+
+ /**
+ * Our height after the last layout
+ */
+ private int mLayoutHeight;
+
+ /**
+ * Sync based on the selected child
+ */
+ static final int SYNC_SELECTED_POSITION = 0;
+
+ /**
+ * Sync based on the first child displayed
+ */
+ static final int SYNC_FIRST_POSITION = 1;
+
+ /**
+ * Maximum amount of time to spend in {@link #findSyncPosition()}
+ */
+ static final int SYNC_MAX_DURATION_MILLIS = 100;
+
+ /**
+ * Indicates that this view is currently being laid out.
+ */
+ boolean mInLayout = false;
+
+ /**
+ * The listener that receives notifications when an item is selected.
+ */
+ OnItemSelectedListener mOnItemSelectedListener;
+
+ /**
+ * The listener that receives notifications when an item is clicked.
+ */
+ OnItemClickListener mOnItemClickListener;
+
+ /**
+ * The listener that receives notifications when an item is long clicked.
+ */
+ OnItemLongClickListener mOnItemLongClickListener;
+
+ /**
+ * True if the data has changed since the last layout
+ */
+ boolean mDataChanged;
+
+ /**
+ * The position within the adapter's data set of the item to select
+ * during the next layout.
+ */
+ int mNextSelectedPosition = INVALID_POSITION;
+
+ /**
+ * The item id of the item to select during the next layout.
+ */
+ long mNextSelectedRowId = INVALID_ROW_ID;
+
+ /**
+ * The position within the adapter's data set of the currently selected item.
+ */
+ int mSelectedPosition = INVALID_POSITION;
+
+ /**
+ * The item id of the currently selected item.
+ */
+ long mSelectedRowId = INVALID_ROW_ID;
+
+ /**
+ * View to show if there are no items to show.
+ */
+ private View mEmptyView;
+
+ /**
+ * The number of items in the current adapter.
+ */
+ int mItemCount;
+
+ /**
+ * The number of items in the adapter before a data changed event occured.
+ */
+ int mOldItemCount;
+
+ /**
+ * Represents an invalid position. All valid positions are in the range 0 to 1 less than the
+ * number of items in the current adapter.
+ */
+ public static final int INVALID_POSITION = -1;
+
+ /**
+ * Represents an empty or invalid row id
+ */
+ public static final long INVALID_ROW_ID = Long.MIN_VALUE;
+
+ /**
+ * The last selected position we used when notifying
+ */
+ int mOldSelectedPosition = INVALID_POSITION;
+
+ /**
+ * The id of the last selected position we used when notifying
+ */
+ long mOldSelectedRowId = INVALID_ROW_ID;
+
+ /**
+ * Indicates what focusable state is requested when calling setFocusable().
+ * In addition to this, this view has other criteria for actually
+ * determining the focusable state (such as whether its empty or the text
+ * filter is shown).
+ *
+ * @see #setFocusable(boolean)
+ * @see #checkFocus()
+ */
+ private boolean mDesiredFocusableState;
+ private boolean mDesiredFocusableInTouchModeState;
+
+ private SelectionNotifier mSelectionNotifier;
+ /**
+ * When set to true, calls to requestLayout() will not propagate up the parent hierarchy.
+ * This is used to layout the children during a layout pass.
+ */
+ boolean mBlockLayoutRequests = false;
+
+ public CustomAdapterView(Context context) {
+ super(context);
+ }
+
+ public CustomAdapterView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomAdapterView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+
+ /**
+ * Interface definition for a callback to be invoked when an item in this
+ * AdapterView has been clicked.
+ */
+ public interface OnItemClickListener {
+
+ /**
+ * Callback method to be invoked when an item in this AdapterView has
+ * been clicked.
+ * <p>
+ * Implementers can call getItemAtPosition(position) if they need
+ * to access the data associated with the selected item.
+ *
+ * @param parent The AdapterView where the click happened.
+ * @param view The view within the AdapterView that was clicked (this
+ * will be a view provided by the adapter)
+ * @param position The position of the view in the adapter.
+ * @param id The row id of the item that was clicked.
+ */
+ void onItemClick(CustomAdapterView<?> parent, View view, int position, long id);
+ }
+
+ /**
+ * Register a callback to be invoked when an item in this AdapterView has
+ * been clicked.
+ *
+ * @param listener The callback that will be invoked.
+ */
+ public void setOnItemClickListener(OnItemClickListener listener) {
+ mOnItemClickListener = listener;
+ }
+
+ /**
+ * @return The callback to be invoked with an item in this AdapterView has
+ * been clicked, or null id no callback has been set.
+ */
+ public final OnItemClickListener getOnItemClickListener() {
+ return mOnItemClickListener;
+ }
+
+ /**
+ * Call the OnItemClickListener, if it is defined.
+ *
+ * @param view The view within the AdapterView that was clicked.
+ * @param position The position of the view in the adapter.
+ * @param id The row id of the item that was clicked.
+ * @return True if there was an assigned OnItemClickListener that was
+ * called, false otherwise is returned.
+ */
+ public boolean performItemClick(View view, int position, long id) {
+ if (mOnItemClickListener != null) {
+ playSoundEffect(SoundEffectConstants.CLICK);
+ mOnItemClickListener.onItemClick(this, view, position, id);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when an item in this
+ * view has been clicked and held.
+ */
+ public interface OnItemLongClickListener {
+ /**
+ * Callback method to be invoked when an item in this view has been
+ * clicked and held.
+ *
+ * Implementers can call getItemAtPosition(position) if they need to access
+ * the data associated with the selected item.
+ *
+ * @param parent The AbsListView where the click happened
+ * @param view The view within the AbsListView that was clicked
+ * @param position The position of the view in the list
+ * @param id The row id of the item that was clicked
+ *
+ * @return true if the callback consumed the long click, false otherwise
+ */
+ boolean onItemLongClick(CustomAdapterView<?> parent, View view, int position, long id);
+ }
+
+
+ /**
+ * Register a callback to be invoked when an item in this AdapterView has
+ * been clicked and held
+ *
+ * @param listener The callback that will run
+ */
+ public void setOnItemLongClickListener(OnItemLongClickListener listener) {
+ if (!isLongClickable()) {
+ setLongClickable(true);
+ }
+ mOnItemLongClickListener = listener;
+ }
+
+ /**
+ * @return The callback to be invoked with an item in this AdapterView has
+ * been clicked and held, or null id no callback as been set.
+ */
+ public final OnItemLongClickListener getOnItemLongClickListener() {
+ return mOnItemLongClickListener;
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when
+ * an item in this view has been selected.
+ */
+ public interface OnItemSelectedListener {
+ /**
+ * Callback method to be invoked when an item in this view has been
+ * selected.
+ *
+ * Impelmenters can call getItemAtPosition(position) if they need to access the
+ * data associated with the selected item.
+ *
+ * @param parent The AdapterView where the selection happened
+ * @param view The view within the AdapterView that was clicked
+ * @param position The position of the view in the adapter
+ * @param id The row id of the item that is selected
+ */
+ void onItemSelected(CustomAdapterView<?> parent, View view, int position, long id);
+
+ /**
+ * Callback method to be invoked when the selection disappears from this
+ * view. The selection can disappear for instance when touch is activated
+ * or when the adapter becomes empty.
+ *
+ * @param parent The AdapterView that now contains no selected item.
+ */
+ void onNothingSelected(CustomAdapterView<?> parent);
+ }
+
+
+ /**
+ * Register a callback to be invoked when an item in this AdapterView has
+ * been selected.
+ *
+ * @param listener The callback that will run
+ */
+ public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+ mOnItemSelectedListener = listener;
+ }
+
+ public final OnItemSelectedListener getOnItemSelectedListener() {
+ return mOnItemSelectedListener;
+ }
+
+ /**
+ * Extra menu information provided to the
+ * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) }
+ * callback when a context menu is brought up for this AdapterView.
+ *
+ */
+ public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo {
+
+ public AdapterContextMenuInfo(View targetView, int position, long id) {
+ this.targetView = targetView;
+ this.position = position;
+ this.id = id;
+ }
+
+ /**
+ * The child view for which the context menu is being displayed. This
+ * will be one of the children of this AdapterView.
+ */
+ public View targetView;
+
+ /**
+ * The position in the adapter for which the context menu is being
+ * displayed.
+ */
+ public int position;
+
+ /**
+ * The row id of the item for which the context menu is being displayed.
+ */
+ public long id;
+ }
+
+ /**
+ * Returns the adapter currently associated with this widget.
+ *
+ * @return The adapter used to provide this view's content.
+ */
+ public abstract T getAdapter();
+
+ /**
+ * Sets the adapter that provides the data and the views to represent the data
+ * in this widget.
+ *
+ * @param adapter The adapter to use to create this view's content.
+ */
+ public abstract void setAdapter(T adapter);
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param child Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void addView(View child) {
+ throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param child Ignored.
+ * @param index Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void addView(View child, int index) {
+ throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param child Ignored.
+ * @param params Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void addView(View child, LayoutParams params) {
+ throw new UnsupportedOperationException("addView(View, LayoutParams) "
+ + "is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param child Ignored.
+ * @param index Ignored.
+ * @param params Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void addView(View child, int index, LayoutParams params) {
+ throw new UnsupportedOperationException("addView(View, int, LayoutParams) "
+ + "is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param child Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void removeView(View child) {
+ throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @param index Ignored.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void removeViewAt(int index) {
+ throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView");
+ }
+
+ /**
+ * This method is not supported and throws an UnsupportedOperationException when called.
+ *
+ * @throws UnsupportedOperationException Every time this method is invoked.
+ */
+ @Override
+ public void removeAllViews() {
+ throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView");
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ mLayoutHeight = getHeight();
+ }
+
+ /**
+ * Return the position of the currently selected item within the adapter's data set
+ *
+ * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected.
+ */
+ @ViewDebug.CapturedViewProperty
+ public int getSelectedItemPosition() {
+ return mNextSelectedPosition;
+ }
+
+ /**
+ * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID}
+ * if nothing is selected.
+ */
+ @ViewDebug.CapturedViewProperty
+ public long getSelectedItemId() {
+ return mNextSelectedRowId;
+ }
+
+ /**
+ * @return The view corresponding to the currently selected item, or null
+ * if nothing is selected
+ */
+ public abstract View getSelectedView();
+
+ /**
+ * @return The data corresponding to the currently selected item, or
+ * null if there is nothing selected.
+ */
+ public Object getSelectedItem() {
+ T adapter = getAdapter();
+ int selection = getSelectedItemPosition();
+ if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
+ return adapter.getItem(selection);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @return The number of items owned by the Adapter associated with this
+ * AdapterView. (This is the number of data items, which may be
+ * larger than the number of visible view.)
+ */
+ @ViewDebug.CapturedViewProperty
+ public int getCount() {
+ return mItemCount;
+ }
+
+ /**
+ * Get the position within the adapter's data set for the view, where view is a an adapter item
+ * or a descendant of an adapter item.
+ *
+ * @param view an adapter item, or a descendant of an adapter item. This must be visible in this
+ * AdapterView at the time of the call.
+ * @return the position within the adapter's data set of the view, or {@link #INVALID_POSITION}
+ * if the view does not correspond to a list item (or it is not currently visible).
+ */
+ public int getPositionForView(View view) {
+ View listItem = view;
+ try {
+ View v;
+ while (!(v = (View) listItem.getParent()).equals(this)) {
+ listItem = v;
+ }
+ } catch (ClassCastException e) {
+ // We made it up to the window without find this list view
+ return INVALID_POSITION;
+ }
+
+ // Search the children for the list item
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (getChildAt(i).equals(listItem)) {
+ return mFirstPosition + i;
+ }
+ }
+
+ // Child not found!
+ return INVALID_POSITION;
+ }
+
+ /**
+ * Returns the position within the adapter's data set for the first item
+ * displayed on screen.
+ *
+ * @return The position within the adapter's data set
+ */
+ public int getFirstVisiblePosition() {
+ return mFirstPosition;
+ }
+
+ /**
+ * Returns the position within the adapter's data set for the last item
+ * displayed on screen.
+ *
+ * @return The position within the adapter's data set
+ */
+ public int getLastVisiblePosition() {
+ return mFirstPosition + getChildCount() - 1;
+ }
+
+ /**
+ * Sets the currently selected item. To support accessibility subclasses that
+ * override this method must invoke the overriden super method first.
+ *
+ * @param position Index (starting at 0) of the data item to be selected.
+ */
+ public abstract void setSelection(int position);
+
+ /**
+ * Sets the view to show if the adapter is empty
+ */
+ public void setEmptyView(View emptyView) {
+ mEmptyView = emptyView;
+
+ final T adapter = getAdapter();
+ final boolean empty = ((adapter == null) || adapter.isEmpty());
+ updateEmptyStatus(empty);
+ }
+
+ /**
+ * When the current adapter is empty, the AdapterView can display a special view
+ * call the empty view. The empty view is used to provide feedback to the user
+ * that no data is available in this AdapterView.
+ *
+ * @return The view to show if the adapter is empty.
+ */
+ public View getEmptyView() {
+ return mEmptyView;
+ }
+
+ /**
+ * Indicates whether this view is in filter mode. Filter mode can for instance
+ * be enabled by a user when typing on the keyboard.
+ *
+ * @return True if the view is in filter mode, false otherwise.
+ */
+ boolean isInFilterMode() {
+ return false;
+ }
+
+ @Override
+ public void setFocusable(boolean focusable) {
+ final T adapter = getAdapter();
+ final boolean empty = adapter == null || adapter.getCount() == 0;
+
+ mDesiredFocusableState = focusable;
+ if (!focusable) {
+ mDesiredFocusableInTouchModeState = false;
+ }
+
+ super.setFocusable(focusable && (!empty || isInFilterMode()));
+ }
+
+ @Override
+ public void setFocusableInTouchMode(boolean focusable) {
+ final T adapter = getAdapter();
+ final boolean empty = adapter == null || adapter.getCount() == 0;
+
+ mDesiredFocusableInTouchModeState = focusable;
+ if (focusable) {
+ mDesiredFocusableState = true;
+ }
+
+ super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode()));
+ }
+
+ void checkFocus() {
+ final T adapter = getAdapter();
+ final boolean empty = adapter == null || adapter.getCount() == 0;
+ final boolean focusable = !empty || isInFilterMode();
+ // The order in which we set focusable in touch mode/focusable may matter
+ // for the client, see View.setFocusableInTouchMode() comments for more
+ // details
+ super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState);
+ super.setFocusable(focusable && mDesiredFocusableState);
+ if (mEmptyView != null) {
+ updateEmptyStatus((adapter == null) || adapter.isEmpty());
+ }
+ }
+
+ /**
+ * Update the status of the list based on the empty parameter. If empty is true and
+ * we have an empty view, display it. In all the other cases, make sure that the listview
+ * is VISIBLE and that the empty view is GONE (if it's not null).
+ */
+ private void updateEmptyStatus(boolean empty) {
+ if (isInFilterMode()) {
+ empty = false;
+ }
+
+ if (empty) {
+ if (mEmptyView != null) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ setVisibility(View.GONE);
+ } else {
+ // If the caller just removed our empty view, make sure the list view is visible
+ setVisibility(View.VISIBLE);
+ }
+
+ // We are now GONE, so pending layouts will not be dispatched.
+ // Force one here to make sure that the state of the list matches
+ // the state of the adapter.
+ if (mDataChanged) {
+ this.onLayout(false, getLeft(), getTop(), getRight(), getBottom());
+ }
+ } else {
+ if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);
+ setVisibility(View.VISIBLE);
+ }
+ }
+
+ /**
+ * Gets the data associated with the specified position in the list.
+ *
+ * @param position Which data to get
+ * @return The data associated with the specified position in the list
+ */
+ public Object getItemAtPosition(int position) {
+ T adapter = getAdapter();
+ return (adapter == null || position < 0) ? null : adapter.getItem(position);
+ }
+
+ public long getItemIdAtPosition(int position) {
+ T adapter = getAdapter();
+ return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);
+ }
+
+ @Override
+ public void setOnClickListener(OnClickListener l) {
+ throw new RuntimeException("Don't call setOnClickListener for an AdapterView. "
+ + "You probably want setOnItemClickListener instead");
+ }
+
+ /**
+ * Override to prevent freezing of any views created by the adapter.
+ */
+ @Override
+ protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
+ dispatchFreezeSelfOnly(container);
+ }
+
+ /**
+ * Override to prevent thawing of any views created by the adapter.
+ */
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ dispatchThawSelfOnly(container);
+ }
+
+ class AdapterDataSetObserver extends DataSetObserver {
+
+ private Parcelable mInstanceState = null;
+
+ @Override
+ public void onChanged() {
+ mDataChanged = true;
+ mOldItemCount = mItemCount;
+ mItemCount = getAdapter().getCount();
+
+ // Detect the case where a cursor that was previously invalidated has
+ // been repopulated with new data.
+ if (CustomAdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
+ && mOldItemCount == 0 && mItemCount > 0) {
+ CustomAdapterView.this.onRestoreInstanceState(mInstanceState);
+ mInstanceState = null;
+ } else {
+ rememberSyncState();
+ }
+ checkFocus();
+ requestLayout();
+ }
+
+ @Override
+ public void onInvalidated() {
+ mDataChanged = true;
+
+ if (CustomAdapterView.this.getAdapter().hasStableIds()) {
+ // Remember the current state for the case where our hosting activity is being
+ // stopped and later restarted
+ mInstanceState = CustomAdapterView.this.onSaveInstanceState();
+ }
+
+ // Data is invalid so we should reset our state
+ mOldItemCount = mItemCount;
+ mItemCount = 0;
+ mSelectedPosition = INVALID_POSITION;
+ mSelectedRowId = INVALID_ROW_ID;
+ mNextSelectedPosition = INVALID_POSITION;
+ mNextSelectedRowId = INVALID_ROW_ID;
+ mNeedSync = false;
+
+ checkFocus();
+ requestLayout();
+ }
+
+ public void clearSavedState() {
+ mInstanceState = null;
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ removeCallbacks(mSelectionNotifier);
+ }
+
+ private class SelectionNotifier implements Runnable {
+ public void run() {
+ if (mDataChanged) {
+ // Data has changed between when this SelectionNotifier
+ // was posted and now. We need to wait until the AdapterView
+ // has been synched to the new data.
+ if (getAdapter() != null) {
+ post(this);
+ }
+ } else {
+ fireOnSelected();
+ }
+ }
+ }
+
+ void selectionChanged() {
+ if (mOnItemSelectedListener != null) {
+ if (mInLayout || mBlockLayoutRequests) {
+ // If we are in a layout traversal, defer notification
+ // by posting. This ensures that the view tree is
+ // in a consistent state and is able to accomodate
+ // new layout or invalidate requests.
+ if (mSelectionNotifier == null) {
+ mSelectionNotifier = new SelectionNotifier();
+ }
+ post(mSelectionNotifier);
+ } else {
+ fireOnSelected();
+ }
+ }
+
+ // we fire selection events here not in View
+ if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ }
+ }
+
+ private void fireOnSelected() {
+ if (mOnItemSelectedListener == null)
+ return;
+
+ int selection = this.getSelectedItemPosition();
+ if (selection >= 0) {
+ View v = getSelectedView();
+ mOnItemSelectedListener.onItemSelected(this, v, selection,
+ getAdapter().getItemId(selection));
+ } else {
+ mOnItemSelectedListener.onNothingSelected(this);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ boolean populated = false;
+ // This is an exceptional case which occurs when a window gets the
+ // focus and sends a focus event via its focused child to announce
+ // current focus/selection. AdapterView fires selection but not focus
+ // events so we change the event type here.
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ }
+
+ // we send selection events only from AdapterView to avoid
+ // generation of such event for each child
+ View selectedView = getSelectedView();
+ if (selectedView != null) {
+ populated = selectedView.dispatchPopulateAccessibilityEvent(event);
+ }
+
+ if (!populated) {
+ if (selectedView != null) {
+ event.setEnabled(selectedView.isEnabled());
+ }
+ event.setItemCount(getCount());
+ event.setCurrentItemIndex(getSelectedItemPosition());
+ }
+
+ return populated;
+ }
+
+ @Override
+ protected boolean canAnimate() {
+ return super.canAnimate() && mItemCount > 0;
+ }
+
+ void handleDataChanged() {
+ final int count = mItemCount;
+ boolean found = false;
+
+ if (count > 0) {
+
+ int newPos;
+
+ // Find the row we are supposed to sync to
+ if (mNeedSync) {
+ // Update this first, since setNextSelectedPositionInt inspects
+ // it
+ mNeedSync = false;
+
+ // See if we can find a position in the new data with the same
+ // id as the old selection
+ newPos = findSyncPosition();
+ if (newPos >= 0) {
+ // Verify that new selection is selectable
+ int selectablePos = lookForSelectablePosition(newPos, true);
+ if (selectablePos == newPos) {
+ // Same row id is selected
+ setNextSelectedPositionInt(newPos);
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ // Try to use the same position if we can't find matching data
+ newPos = getSelectedItemPosition();
+
+ // Pin position to the available range
+ if (newPos >= count) {
+ newPos = count - 1;
+ }
+ if (newPos < 0) {
+ newPos = 0;
+ }
+
+ // Make sure we select something selectable -- first look down
+ int selectablePos = lookForSelectablePosition(newPos, true);
+ if (selectablePos < 0) {
+ // Looking down didn't work -- try looking up
+ selectablePos = lookForSelectablePosition(newPos, false);
+ }
+ if (selectablePos >= 0) {
+ setNextSelectedPositionInt(selectablePos);
+ checkSelectionChanged();
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ // Nothing is selected
+ mSelectedPosition = INVALID_POSITION;
+ mSelectedRowId = INVALID_ROW_ID;
+ mNextSelectedPosition = INVALID_POSITION;
+ mNextSelectedRowId = INVALID_ROW_ID;
+ mNeedSync = false;
+ checkSelectionChanged();
+ }
+ }
+
+ void checkSelectionChanged() {
+ if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
+ selectionChanged();
+ mOldSelectedPosition = mSelectedPosition;
+ mOldSelectedRowId = mSelectedRowId;
+ }
+ }
+
+ /**
+ * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition
+ * and then alternates between moving up and moving down until 1) we find the right position, or
+ * 2) we run out of time, or 3) we have looked at every position
+ *
+ * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't
+ * be found
+ */
+ int findSyncPosition() {
+ int count = mItemCount;
+
+ if (count == 0) {
+ return INVALID_POSITION;
+ }
+
+ long idToMatch = mSyncRowId;
+ int seed = mSyncPosition;
+
+ // If there isn't a selection don't hunt for it
+ if (idToMatch == INVALID_ROW_ID) {
+ return INVALID_POSITION;
+ }
+
+ // Pin seed to reasonable values
+ seed = Math.max(0, seed);
+ seed = Math.min(count - 1, seed);
+
+ long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS;
+
+ long rowId;
+
+ // first position scanned so far
+ int first = seed;
+
+ // last position scanned so far
+ int last = seed;
+
+ // True if we should move down on the next iteration
+ boolean next = false;
+
+ // True when we have looked at the first item in the data
+ boolean hitFirst;
+
+ // True when we have looked at the last item in the data
+ boolean hitLast;
+
+ // Get the item ID locally (instead of getItemIdAtPosition), so
+ // we need the adapter
+ T adapter = getAdapter();
+ if (adapter == null) {
+ return INVALID_POSITION;
+ }
+
+ while (SystemClock.uptimeMillis() <= endTime) {
+ rowId = adapter.getItemId(seed);
+ if (rowId == idToMatch) {
+ // Found it!
+ return seed;
+ }
+
+ hitLast = last == count - 1;
+ hitFirst = first == 0;
+
+ if (hitLast && hitFirst) {
+ // Looked at everything
+ break;
+ }
+
+ if (hitFirst || (next && !hitLast)) {
+ // Either we hit the top, or we are trying to move down
+ last++;
+ seed = last;
+ // Try going up next time
+ next = false;
+ } else if (hitLast || (!next && !hitFirst)) {
+ // Either we hit the bottom, or we are trying to move up
+ first--;
+ seed = first;
+ // Try going down next time
+ next = true;
+ }
+
+ }
+
+ return INVALID_POSITION;
+ }
+
+ /**
+ * Find a position that can be selected (i.e., is not a separator).
+ *
+ * @param position The starting position to look at.
+ * @param lookDown Whether to look down for other positions.
+ * @return The next selectable position starting at position and then searching either up or
+ * down. Returns {@link #INVALID_POSITION} if nothing can be found.
+ */
+ int lookForSelectablePosition(int position, boolean lookDown) {
+ return position;
+ }
+
+ /**
+ * Utility to keep mSelectedPosition and mSelectedRowId in sync
+ * @param position Our current position
+ */
+ void setSelectedPositionInt(int position) {
+ mSelectedPosition = position;
+ mSelectedRowId = getItemIdAtPosition(position);
+ }
+
+ /**
+ * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync
+ * @param position Intended value for mSelectedPosition the next time we go
+ * through layout
+ */
+ void setNextSelectedPositionInt(int position) {
+ mNextSelectedPosition = position;
+ mNextSelectedRowId = getItemIdAtPosition(position);
+ // If we are trying to sync to the selection, update that too
+ if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) {
+ mSyncPosition = position;
+ mSyncRowId = mNextSelectedRowId;
+ }
+ }
+
+ /**
+ * Remember enough information to restore the screen state when the data has
+ * changed.
+ *
+ */
+ void rememberSyncState() {
+ if (getChildCount() > 0) {
+ mNeedSync = true;
+ mSyncHeight = mLayoutHeight;
+ if (mSelectedPosition >= 0) {
+ // Sync the selection state
+ View v = getChildAt(mSelectedPosition - mFirstPosition);
+ mSyncRowId = mNextSelectedRowId;
+ mSyncPosition = mNextSelectedPosition;
+ if (v != null) {
+ mSpecificTop = v.getTop();
+ }
+ mSyncMode = SYNC_SELECTED_POSITION;
+ } else {
+ // Sync the based on the offset of the first view
+ View v = getChildAt(0);
+ T adapter = getAdapter();
+ if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) {
+ mSyncRowId = adapter.getItemId(mFirstPosition);
+ } else {
+ mSyncRowId = NO_ID;
+ }
+ mSyncPosition = mFirstPosition;
+ if (v != null) {
+ mSpecificTop = v.getTop();
+ }
+ mSyncMode = SYNC_FIRST_POSITION;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/trebuchet/widget/EcoGallery.java b/src/com/cyanogenmod/trebuchet/widget/EcoGallery.java
new file mode 100644
index 0000000..d70a37e
--- /dev/null
+++ b/src/com/cyanogenmod/trebuchet/widget/EcoGallery.java
@@ -0,0 +1,1415 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.trebuchet.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.Transformation;
+import android.widget.Scroller;
+import com.cyanogenmod.trebuchet.R;
+
+import java.lang.reflect.Field;
+
+public class EcoGallery extends CustomAbsSpinner implements GestureDetector.OnGestureListener {
+
+ private static final String TAG = "Gallery";
+
+ private static final boolean localLOGV = false;
+
+ /**
+ * Duration in milliseconds from the start of a scroll during which we're
+ * unsure whether the user is scrolling or flinging.
+ */
+ private static final int SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT = 250;
+
+ private static final String LOG_TAG = null;
+
+ /**
+ * Horizontal spacing between items.
+ */
+ private int mSpacing = 0;
+
+ /**
+ * How long the transition animation should run when a child view changes
+ * position, measured in milliseconds.
+ */
+ private int mAnimationDuration = 200;
+
+ /**
+ * The alpha of items that are not selected.
+ */
+ private float mUnselectedAlpha;
+
+ /**
+ * Left most edge of a child seen so far during layout.
+ */
+ private int mLeftMost;
+
+ /**
+ * Right most edge of a child seen so far during layout.
+ */
+ private int mRightMost;
+
+ private int mGravity;
+
+ /**
+ * Helper for detecting touch gestures.
+ */
+ private GestureDetector mGestureDetector;
+
+ /**
+ * The position of the item that received the user's down touch.
+ */
+ private int mDownTouchPosition;
+
+ /**
+ * The view of the item that received the user's down touch.
+ */
+ private View mDownTouchView;
+
+ /**
+ * Executes the delta scrolls from a fling or scroll movement.
+ */
+ private FlingRunnable mFlingRunnable = new FlingRunnable();
+
+ /**
+ * Sets mSuppressSelectionChanged = false. This is used to set it to false
+ * in the future. It will also trigger a selection changed.
+ */
+ private Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() {
+ public void run() {
+ mSuppressSelectionChanged = false;
+ selectionChanged();
+ }
+ };
+
+ /**
+ * When fling runnable runs, it resets this to false. Any method along the
+ * path until the end of its run() can set this to true to abort any
+ * remaining fling. For example, if we've reached either the leftmost or
+ * rightmost item, we will set this to true.
+ */
+ private boolean mShouldStopFling;
+
+ /**
+ * The currently selected item's child.
+ */
+ private View mSelectedChild;
+
+ /**
+ * Whether to continuously callback on the item selected listener during a
+ * fling.
+ */
+ private boolean mShouldCallbackDuringFling = true;
+
+ /**
+ * Whether to callback when an item that is not selected is clicked.
+ */
+ private boolean mShouldCallbackOnUnselectedItemClick = true;
+
+ /**
+ * If true, do not callback to item selected listener.
+ */
+ private boolean mSuppressSelectionChanged;
+
+ /**
+ * If true, we have received the "invoke" (center or enter buttons) key
+ * down. This is checked before we action on the "invoke" key up, and is
+ * subsequently cleared.
+ */
+ private boolean mReceivedInvokeKeyDown;
+
+ private AdapterContextMenuInfo mContextMenuInfo;
+
+
+ /**
+ * If true, this onScroll is the first for this user's drag (remember, a
+ * drag sends many onScrolls).
+ */
+ private boolean mIsFirstScroll;
+
+
+ /**
+ * If true the reflection calls failed and this widget will behave
+ * unpredictably if used further
+ */
+ private boolean mBroken;
+
+ public EcoGallery(Context context) {
+ this(context, null);
+ }
+
+ public EcoGallery(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.ecoGalleryStyle);
+ }
+
+ public EcoGallery(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mBroken = true;
+
+ mGestureDetector = new GestureDetector(context, this);
+ mGestureDetector.setIsLongpressEnabled(true);
+
+ TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.EcoGallery, defStyle, 0);
+
+ int index = a.getInt(R.styleable.EcoGallery_gravity, -1);
+ if (index >= 0) {
+ setGravity(index);
+ }
+
+ int animationDuration =
+ a.getInt(R.styleable.EcoGallery_animationDuration, -1);
+ if (animationDuration > 0) {
+ setAnimationDuration(animationDuration);
+ }
+
+ int spacing =
+ a.getDimensionPixelOffset(R.styleable.EcoGallery_spacing, 0);
+ setSpacing(spacing);
+
+ float unselectedAlpha = a.getFloat(
+ R.styleable.EcoGallery_unselectedAlpha, 0.5f);
+ setUnselectedAlpha(unselectedAlpha);
+
+ a.recycle();
+
+ // We draw the selected item last (because otherwise the item to the
+ // right overlaps it)
+ int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
+ int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
+ Class vgClass = ViewGroup.class;
+
+ try {
+ Field childDrawingOrder = vgClass
+ .getDeclaredField("FLAG_USE_CHILD_DRAWING_ORDER");
+ Field supportStaticTrans = vgClass
+ .getDeclaredField("FLAG_SUPPORT_STATIC_TRANSFORMATIONS");
+
+ childDrawingOrder.setAccessible(true);
+ supportStaticTrans.setAccessible(true);
+
+ FLAG_USE_CHILD_DRAWING_ORDER = childDrawingOrder.getInt(this);
+ FLAG_SUPPORT_STATIC_TRANSFORMATIONS = supportStaticTrans.getInt(this);
+ } catch (NoSuchFieldException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ try {
+ // set new group flags
+ Field groupFlags = vgClass.getDeclaredField("mGroupFlags");
+ groupFlags.setAccessible(true);
+ int groupFlagsValue = groupFlags.getInt(this);
+
+ groupFlagsValue |= FLAG_USE_CHILD_DRAWING_ORDER;
+ groupFlagsValue |= FLAG_SUPPORT_STATIC_TRANSFORMATIONS;
+
+ groupFlags.set(this, groupFlagsValue);
+
+ // working!
+ mBroken = false;
+ } catch (NoSuchFieldException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @return Whether the widget is broken or working (functional)
+ */
+ public boolean isBroken() {
+ return mBroken;
+ }
+
+ /**
+ * Whether or not to callback on any {@link #getOnItemSelectedListener()}
+ * while the items are being flinged. If false, only the final selected item
+ * will cause the callback. If true, all items between the first and the
+ * final will cause callbacks.
+ *
+ * @param shouldCallback Whether or not to callback on the listener while
+ * the items are being flinged.
+ */
+ public void setCallbackDuringFling(boolean shouldCallback) {
+ mShouldCallbackDuringFling = shouldCallback;
+ }
+
+ /**
+ * Whether or not to callback when an item that is not selected is clicked.
+ * If false, the item will become selected (and re-centered). If true, the
+ * {@link #getOnItemClickListener()} will get the callback.
+ *
+ * @param shouldCallback Whether or not to callback on the listener when a
+ * item that is not selected is clicked.
+ * @hide
+ */
+ public void setCallbackOnUnselectedItemClick(boolean shouldCallback) {
+ mShouldCallbackOnUnselectedItemClick = shouldCallback;
+ }
+
+ /**
+ * Sets how long the transition animation should run when a child view
+ * changes position. Only relevant if animation is turned on.
+ *
+ * @param animationDurationMillis The duration of the transition, in
+ * milliseconds.
+ *
+ * @attr ref android.R.styleable#Gallery_animationDuration
+ */
+ public void setAnimationDuration(int animationDurationMillis) {
+ mAnimationDuration = animationDurationMillis;
+ }
+
+ /**
+ * Sets the spacing between items in a Gallery
+ *
+ * @param spacing The spacing in pixels between items in the Gallery
+ *
+ * @attr ref android.R.styleable#Gallery_spacing
+ */
+ public void setSpacing(int spacing) {
+ mSpacing = spacing;
+ }
+
+ /**
+ * Sets the alpha of items that are not selected in the Gallery.
+ *
+ * @param unselectedAlpha the alpha for the items that are not selected.
+ *
+ * @attr ref android.R.styleable#Gallery_unselectedAlpha
+ */
+ public void setUnselectedAlpha(float unselectedAlpha) {
+ mUnselectedAlpha = unselectedAlpha;
+ }
+
+ @Override
+ protected boolean getChildStaticTransformation(View child, Transformation t) {
+
+ t.clear();
+ t.setAlpha(child == mSelectedChild ? 1.0f : mUnselectedAlpha);
+
+ return true;
+ }
+
+ @Override
+ protected int computeHorizontalScrollExtent() {
+ // Only 1 item is considered to be selected
+ return 1;
+ }
+
+ @Override
+ protected int computeHorizontalScrollOffset() {
+ // Current scroll position is the same as the selected position
+ return mSelectedPosition;
+ }
+
+ @Override
+ protected int computeHorizontalScrollRange() {
+ // Scroll range is the same as the item count
+ return mItemCount;
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ /*
+ * Gallery expects EcoGallery.LayoutParams.
+ */
+ return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+
+ /*
+ * Remember that we are in layout to prevent more layout request from
+ * being generated.
+ */
+ mInLayout = true;
+ layout(0, false);
+
+ mInLayout = false;
+ }
+
+ @Override
+ int getChildHeight(View child) {
+ return child.getMeasuredHeight();
+ }
+
+ /**
+ * Tracks a motion scroll. In reality, this is used to do just about any
+ * movement to items (touch scroll, arrow-key scroll, set an item as selected).
+ *
+ * @param deltaX Change in X from the previous event.
+ */
+ void trackMotionScroll(int deltaX) {
+
+ if (getChildCount() == 0) {
+ return;
+ }
+
+ boolean toLeft = deltaX < 0;
+
+ int limitedDeltaX = getLimitedMotionScrollAmount(toLeft, deltaX);
+ if (limitedDeltaX != deltaX) {
+ // The above call returned a limited amount, so stop any scrolls/flings
+ mFlingRunnable.endFling(false);
+ onFinishedMovement();
+ }
+
+ offsetChildrenLeftAndRight(limitedDeltaX);
+
+ detachOffScreenChildren(toLeft);
+
+ if (toLeft) {
+ // If moved left, there will be empty space on the right
+ fillToGalleryRight();
+ } else {
+ // Similarly, empty space on the left
+ fillToGalleryLeft();
+ }
+
+ setSelectionToCenterChild();
+
+ invalidate();
+ }
+
+ int getLimitedMotionScrollAmount(boolean motionToLeft, int deltaX) {
+ int extremeItemPosition = motionToLeft ? mItemCount - 1 : 0;
+ View extremeChild = getChildAt(extremeItemPosition - mFirstPosition);
+
+ if (extremeChild == null) {
+ return deltaX;
+ }
+
+ int extremeChildCenter = getCenterOfView(extremeChild);
+ int galleryCenter = getCenterOfGallery();
+
+ if (motionToLeft) {
+ if (extremeChildCenter <= galleryCenter) {
+
+ // The extreme child is past his boundary point!
+ return 0;
+ }
+ } else {
+ if (extremeChildCenter >= galleryCenter) {
+
+ // The extreme child is past his boundary point!
+ return 0;
+ }
+ }
+
+ int centerDifference = galleryCenter - extremeChildCenter;
+
+ return motionToLeft
+ ? Math.max(centerDifference, deltaX)
+ : Math.min(centerDifference, deltaX);
+ }
+
+ /**
+ * Offset the horizontal location of all children of this view by the
+ * specified number of pixels.
+ *
+ * @param offset the number of pixels to offset
+ */
+ private void offsetChildrenLeftAndRight(int offset) {
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ getChildAt(i).offsetLeftAndRight(offset);
+ }
+ }
+
+ /**
+ * @return The center of this Gallery.
+ */
+ private int getCenterOfGallery() {
+ int paddingLeft = getPaddingLeft();
+ return (getWidth() - paddingLeft - getPaddingRight()) / 2 + paddingLeft;
+ }
+
+ /**
+ * @return The center of the given view.
+ */
+ private static int getCenterOfView(View view) {
+ return view.getLeft() + view.getWidth() / 2;
+ }
+
+ /**
+ * Detaches children that are off the screen (i.e.: Gallery bounds).
+ *
+ * @param toLeft Whether to detach children to the left of the Gallery, or
+ * to the right.
+ */
+ private void detachOffScreenChildren(boolean toLeft) {
+ int numChildren = getChildCount();
+ int firstPosition = mFirstPosition;
+ int start = 0;
+ int count = 0;
+
+ if (toLeft) {
+ final int galleryLeft = getPaddingLeft();
+ for (int i = 0; i < numChildren; i++) {
+ final View child = getChildAt(i);
+ if (child.getRight() >= galleryLeft) {
+ break;
+ } else {
+ count++;
+ mRecycler.add(firstPosition + i, child);
+ }
+ }
+ } else {
+ final int galleryRight = getWidth() - getPaddingRight();
+ for (int i = numChildren - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+ if (child.getLeft() <= galleryRight) {
+ break;
+ } else {
+ start = i;
+ count++;
+ mRecycler.add(firstPosition + i, child);
+ }
+ }
+ }
+
+ detachViewsFromParent(start, count);
+
+ if (toLeft) {
+ mFirstPosition += count;
+ }
+ }
+
+ /**
+ * Scrolls the items so that the selected item is in its 'slot' (its center
+ * is the gallery's center).
+ */
+ private void scrollIntoSlots() {
+
+ if (getChildCount() == 0 || mSelectedChild == null) return;
+
+ int selectedCenter = getCenterOfView(mSelectedChild);
+ int targetCenter = getCenterOfGallery();
+
+ int scrollAmount = targetCenter - selectedCenter;
+ if (scrollAmount != 0) {
+ mFlingRunnable.startUsingDistance(scrollAmount);
+ } else {
+ onFinishedMovement();
+ }
+ }
+
+ private void onFinishedMovement() {
+ if (mSuppressSelectionChanged) {
+ mSuppressSelectionChanged = false;
+
+ // We haven't been callbacking during the fling, so do it now
+ super.selectionChanged();
+ }
+ invalidate();
+ }
+
+ @Override
+ void selectionChanged() {
+ if (!mSuppressSelectionChanged) {
+ super.selectionChanged();
+ }
+ }
+
+ /**
+ * Looks for the child that is closest to the center and sets it as the
+ * selected child.
+ */
+ private void setSelectionToCenterChild() {
+
+ View selView = mSelectedChild;
+ if (mSelectedChild == null) return;
+
+ int galleryCenter = getCenterOfGallery();
+
+ // Common case where the current selected position is correct
+ if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
+ return;
+ }
+
+ // TODO better search
+ int closestEdgeDistance = Integer.MAX_VALUE;
+ int newSelectedChildIndex = 0;
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+
+ View child = getChildAt(i);
+
+ if (child.getLeft() <= galleryCenter && child.getRight() >= galleryCenter) {
+ // This child is in the center
+ newSelectedChildIndex = i;
+ break;
+ }
+
+ int childClosestEdgeDistance = Math.min(Math.abs(child.getLeft() - galleryCenter),
+ Math.abs(child.getRight() - galleryCenter));
+ if (childClosestEdgeDistance < closestEdgeDistance) {
+ closestEdgeDistance = childClosestEdgeDistance;
+ newSelectedChildIndex = i;
+ }
+ }
+
+ int newPos = mFirstPosition + newSelectedChildIndex;
+
+ if (newPos != mSelectedPosition) {
+ setSelectedPositionInt(newPos);
+ setNextSelectedPositionInt(newPos);
+ checkSelectionChanged();
+ }
+ }
+
+ /**
+ * Creates and positions all views for this Gallery.
+ * <p>
+ * We layout rarely, most of the time {@link #trackMotionScroll(int)} takes
+ * care of repositioning, adding, and removing children.
+ *
+ * @param delta Change in the selected position. +1 means the selection is
+ * moving to the right, so views are scrolling to the left. -1
+ * means the selection is moving to the left.
+ */
+ @Override
+ void layout(int delta, boolean animate) {
+
+ int childrenLeft = mSpinnerPadding.left;
+ int childrenWidth = getRight() - getLeft() - mSpinnerPadding.left - mSpinnerPadding.right;
+
+ if (mDataChanged) {
+ handleDataChanged();
+ }
+
+ // Handle an empty gallery by removing all views.
+ if (mItemCount == 0) {
+ resetList();
+ return;
+ }
+
+ // Update to the new selected position.
+ if (mNextSelectedPosition >= 0) {
+ setSelectedPositionInt(mNextSelectedPosition);
+ }
+
+ // All views go in recycler while we are in layout
+ recycleAllViews();
+
+ // Clear out old views
+ detachAllViewsFromParent();
+
+ /*
+ * These will be used to give initial positions to views entering the
+ * gallery as we scroll
+ */
+ mRightMost = 0;
+ mLeftMost = 0;
+
+ // Make selected view and center it
+
+ /*
+ * mFirstPosition will be decreased as we add views to the left later
+ * on. The 0 for x will be offset in a couple lines down.
+ */
+ mFirstPosition = mSelectedPosition;
+ View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
+
+ // Put the selected child in the center
+ int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
+ sel.offsetLeftAndRight(selectedOffset);
+
+ fillToGalleryRight();
+ fillToGalleryLeft();
+
+ invalidate();
+ checkSelectionChanged();
+
+ mDataChanged = false;
+ mNeedSync = false;
+ setNextSelectedPositionInt(mSelectedPosition);
+
+ updateSelectedItemMetadata();
+ }
+
+ private void fillToGalleryLeft() {
+ int itemSpacing = mSpacing;
+ int galleryLeft = getPaddingLeft();
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(0);
+ int curPosition;
+ int curRightEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition - 1;
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ } else {
+ // No children available!
+ curPosition = 0;
+ curRightEdge = getRight() - getLeft() - getPaddingRight();
+ mShouldStopFling = true;
+ }
+
+ while (curRightEdge > galleryLeft && curPosition >= 0) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curRightEdge, false);
+
+ // Remember some state
+ mFirstPosition = curPosition;
+
+ // Set state for next iteration
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ curPosition--;
+ }
+ }
+
+ private void fillToGalleryRight() {
+ int itemSpacing = mSpacing;
+ int galleryRight = getRight() - getLeft() - getPaddingRight();
+ int numChildren = getChildCount();
+ int numItems = mItemCount;
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(numChildren - 1);
+ int curPosition;
+ int curLeftEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition + numChildren;
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ } else {
+ mFirstPosition = curPosition = mItemCount - 1;
+ curLeftEdge = getPaddingLeft();
+ mShouldStopFling = true;
+ }
+
+ while (curLeftEdge < galleryRight && curPosition < numItems) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curLeftEdge, true);
+
+ // Set state for next iteration
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ curPosition++;
+ }
+ }
+
+ /**
+ * Obtain a view, either by pulling an existing view from the recycler or by
+ * getting a new one from the adapter. If we are animating, make sure there
+ * is enough information in the view's layout parameters to animate from the
+ * old to new positions.
+ *
+ * @param position Position in the gallery for the view to obtain
+ * @param offset Offset from the selected position
+ * @param x X-coordinate indicating where this view should be placed. This
+ * will either be the left or right edge of the view, depending on
+ * the fromLeft parameter
+ * @param fromLeft Are we positioning views based on the left edge? (i.e.,
+ * building from left to right)?
+ * @return A view that has been added to the gallery
+ */
+ private View makeAndAddView(int position, int offset, int x,
+ boolean fromLeft) {
+
+ View child;
+
+ child = mRecycler.get();
+ // pass child as convertview
+ child = mAdapter.getView(position, child, this);
+
+ // Position the view
+ setUpChild(child, offset, x, fromLeft);
+
+ return child;
+ }
+
+ /**
+ * Helper for makeAndAddView to set the position of a view and fill out its
+ * layout paramters.
+ *
+ * @param child The view to position
+ * @param offset Offset from the selected position
+ * @param x X-coordintate indicating where this view should be placed. This
+ * will either be the left or right edge of the view, depending on
+ * the fromLeft paramter
+ * @param fromLeft Are we posiitoning views based on the left edge? (i.e.,
+ * building from left to right)?
+ */
+ private void setUpChild(View child, int offset, int x, boolean fromLeft) {
+
+ // Respect layout params that are already in the view. Otherwise
+ // make some up...
+ LayoutParams lp = (LayoutParams)
+ child.getLayoutParams();
+ if (lp == null) {
+ lp = (LayoutParams) generateDefaultLayoutParams();
+ }
+
+ addViewInLayout(child, fromLeft ? -1 : 0, lp);
+
+ child.setSelected(offset == 0);
+
+ // Get measure specs
+ int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
+ mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
+ int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
+ mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
+
+ // Measure child
+ child.measure(childWidthSpec, childHeightSpec);
+
+ int childLeft;
+ int childRight;
+
+ // Position vertically based on gravity setting
+ int childTop = calculateTop(child, true);
+ int childBottom = childTop + child.getMeasuredHeight();
+
+ int width = child.getMeasuredWidth();
+ if (fromLeft) {
+ childLeft = x;
+ childRight = childLeft + width;
+ } else {
+ childLeft = x - width;
+ childRight = x;
+ }
+
+ child.layout(childLeft, childTop, childRight, childBottom);
+ }
+
+ /**
+ * Figure out vertical placement based on mGravity
+ *
+ * @param child Child to place
+ * @return Where the top of the child should be
+ */
+ private int calculateTop(View child, boolean duringLayout) {
+ int myHeight = duringLayout ? getMeasuredHeight() : getHeight();
+ int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight();
+
+ int childTop = 0;
+
+ switch (mGravity) {
+ case Gravity.TOP:
+ childTop = mSpinnerPadding.top;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ int availableSpace = myHeight - mSpinnerPadding.bottom
+ - mSpinnerPadding.top - childHeight;
+ childTop = mSpinnerPadding.top + (availableSpace / 2);
+ break;
+ case Gravity.BOTTOM:
+ childTop = myHeight - mSpinnerPadding.bottom - childHeight;
+ break;
+ }
+ return childTop;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+
+ // Give everything to the gesture detector
+ boolean retValue = mGestureDetector.onTouchEvent(event);
+
+ int action = event.getAction();
+ if (action == MotionEvent.ACTION_UP) {
+ // Helper method for lifted finger
+ onUp();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ onCancel();
+ }
+
+ return retValue;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onSingleTapUp(MotionEvent e) {
+
+ if (mDownTouchPosition >= 0) {
+
+ // An item tap should make it selected, so scroll to this child.
+ scrollToChild(mDownTouchPosition - mFirstPosition);
+
+ // Also pass the click so the client knows, if it wants to.
+ if (mShouldCallbackOnUnselectedItemClick || mDownTouchPosition == mSelectedPosition) {
+ performItemClick(mDownTouchView, mDownTouchPosition, mAdapter
+ .getItemId(mDownTouchPosition));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+
+ if (!mShouldCallbackDuringFling) {
+ // We want to suppress selection changes
+
+ // Remove any future code to set mSuppressSelectionChanged = false
+ removeCallbacks(mDisableSuppressSelectionChangedRunnable);
+
+ // This will get reset once we scroll into slots
+ if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
+ }
+
+ // Fling the gallery!
+ mFlingRunnable.startUsingVelocity((int) -velocityX);
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+
+ if (localLOGV) Log.v(TAG, String.valueOf(e2.getX() - e1.getX()));
+
+ /*
+ * Now's a good time to tell our parent to stop intercepting our events!
+ * The user has moved more than the slop amount, since GestureDetector
+ * ensures this before calling this method. Also, if a parent is more
+ * interested in this touch's events than we are, it would have
+ * intercepted them by now (for example, we can assume when a Gallery is
+ * in the ListView, a vertical scroll would not end up in this method
+ * since a ListView would have intercepted it by now).
+ */
+ getParent().requestDisallowInterceptTouchEvent(true);
+
+ // As the user scrolls, we want to callback selection changes so related-
+ // info on the screen is up-to-date with the gallery's selection
+ if (!mShouldCallbackDuringFling) {
+ if (mIsFirstScroll) {
+ /*
+ * We're not notifying the client of selection changes during
+ * the fling, and this scroll could possibly be a fling. Don't
+ * do selection changes until we're sure it is not a fling.
+ */
+ if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
+ postDelayed(mDisableSuppressSelectionChangedRunnable, SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT);
+ }
+ } else {
+ if (mSuppressSelectionChanged) mSuppressSelectionChanged = false;
+ }
+
+ // Track the motion
+ trackMotionScroll(-1 * (int) distanceX);
+
+ mIsFirstScroll = false;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onDown(MotionEvent e) {
+
+ // Kill any existing fling/scroll
+ mFlingRunnable.stop(false);
+
+ // Get the item's view that was touched
+ mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY());
+
+ if (mDownTouchPosition >= 0) {
+ mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition);
+ mDownTouchView.setPressed(true);
+ }
+
+ // Reset the multiple-scroll tracking state
+ mIsFirstScroll = true;
+
+ // Must return true to get matching events for this down event.
+ return true;
+ }
+
+ /**
+ * Called when a touch event's action is MotionEvent.ACTION_UP.
+ */
+ void onUp() {
+
+ if (mFlingRunnable.mScroller.isFinished()) {
+ scrollIntoSlots();
+ }
+
+ dispatchUnpress();
+ }
+
+ /**
+ * Called when a touch event's action is MotionEvent.ACTION_CANCEL.
+ */
+ void onCancel() {
+ onUp();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onLongPress(MotionEvent e) {
+
+ if (mDownTouchPosition < 0) {
+ return;
+ }
+
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ long id = getItemIdAtPosition(mDownTouchPosition);
+ dispatchLongPress(mDownTouchView, mDownTouchPosition, id);
+ }
+
+ // Unused methods from GestureDetector.OnGestureListener below
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onShowPress(MotionEvent e) {
+ }
+
+ // Unused methods from GestureDetector.OnGestureListener above
+
+ private void dispatchPress(View child) {
+
+ if (child != null) {
+ child.setPressed(true);
+ }
+
+ setPressed(true);
+ }
+
+ private void dispatchUnpress() {
+
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ getChildAt(i).setPressed(false);
+ }
+
+ setPressed(false);
+ }
+
+ @Override
+ public void dispatchSetSelected(boolean selected) {
+ /*
+ * We don't want to pass the selected state given from its parent to its
+ * children since this widget itself has a selected state to give to its
+ * children.
+ */
+ }
+
+ @Override
+ protected void dispatchSetPressed(boolean pressed) {
+
+ // Show the pressed state on the selected child
+ if (mSelectedChild != null) {
+ mSelectedChild.setPressed(pressed);
+ }
+ }
+
+ @Override
+ protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
+ return mContextMenuInfo;
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView) {
+
+ final int longPressPosition = getPositionForView(originalView);
+ if (longPressPosition < 0) {
+ return false;
+ }
+
+ final long longPressId = mAdapter.getItemId(longPressPosition);
+ return dispatchLongPress(originalView, longPressPosition, longPressId);
+ }
+
+ @Override
+ public boolean showContextMenu() {
+
+ if (isPressed() && mSelectedPosition >= 0) {
+ int index = mSelectedPosition - mFirstPosition;
+ View v = getChildAt(index);
+ return dispatchLongPress(v, mSelectedPosition, mSelectedRowId);
+ }
+
+ return false;
+ }
+
+ private boolean dispatchLongPress(View view, int position, long id) {
+ boolean handled = false;
+
+ if (mOnItemLongClickListener != null) {
+ handled = mOnItemLongClickListener.onItemLongClick(this, mDownTouchView,
+ mDownTouchPosition, id);
+ }
+
+ if (!handled) {
+ mContextMenuInfo = new AdapterContextMenuInfo(view, position, id);
+ handled = super.showContextMenuForChild(this);
+ }
+
+ if (handled) {
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+
+ return handled;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Gallery steals all key events
+ return event.dispatch(this, null, null);
+ }
+
+ /**
+ * Handles left, right, and clicking
+ * @see android.view.View#onKeyDown
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (movePrevious()) {
+ playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
+ }
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (moveNext()) {
+ playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
+ }
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER:
+ mReceivedInvokeKeyDown = true;
+ // fallthrough to default handling
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER: {
+
+ if (mReceivedInvokeKeyDown) {
+ if (mItemCount > 0) {
+
+ dispatchPress(mSelectedChild);
+ postDelayed(new Runnable() {
+ public void run() {
+ dispatchUnpress();
+ }
+ }, ViewConfiguration.getPressedStateDuration());
+
+ int selectedIndex = mSelectedPosition - mFirstPosition;
+ performItemClick(getChildAt(selectedIndex), mSelectedPosition, mAdapter
+ .getItemId(mSelectedPosition));
+ }
+ }
+
+ // Clear the flag
+ mReceivedInvokeKeyDown = false;
+
+ return true;
+ }
+ }
+
+ return super.onKeyUp(keyCode, event);
+ }
+
+ boolean movePrevious() {
+ if (mItemCount > 0 && mSelectedPosition > 0) {
+ scrollToChild(mSelectedPosition - mFirstPosition - 1);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ boolean moveNext() {
+ if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ scrollToChild(mSelectedPosition - mFirstPosition + 1);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean scrollToChild(int childPosition) {
+ View child = getChildAt(childPosition);
+
+ if (child != null) {
+ int distance = getCenterOfGallery() - getCenterOfView(child);
+ mFlingRunnable.startUsingDistance(distance);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ void setSelectedPositionInt(int position) {
+ super.setSelectedPositionInt(position);
+
+ // Updates any metadata we keep about the selected item.
+ updateSelectedItemMetadata();
+ }
+
+ private void updateSelectedItemMetadata() {
+
+ View oldSelectedChild = mSelectedChild;
+
+ View child = mSelectedChild = getChildAt(mSelectedPosition - mFirstPosition);
+ if (child == null) {
+ return;
+ }
+
+ child.setSelected(true);
+ child.setFocusable(true);
+
+ if (hasFocus()) {
+ child.requestFocus();
+ }
+
+ // We unfocus the old child down here so the above hasFocus check
+ // returns true
+ if (oldSelectedChild != null) {
+
+ // Make sure its drawable state doesn't contain 'selected'
+ oldSelectedChild.setSelected(false);
+
+ // Make sure it is not focusable anymore, since otherwise arrow keys
+ // can make this one be focused
+ oldSelectedChild.setFocusable(false);
+ }
+
+ }
+
+ /**
+ * Describes how the child views are aligned.
+ * @param gravity
+ *
+ * @attr ref android.R.styleable#Gallery_gravity
+ */
+ public void setGravity(int gravity)
+ {
+ if (mGravity != gravity) {
+ mGravity = gravity;
+ requestLayout();
+ }
+ }
+
+ @Override
+ protected int getChildDrawingOrder(int childCount, int i) {
+ int selectedIndex = mSelectedPosition - mFirstPosition;
+
+ // Just to be safe
+ if (selectedIndex < 0) return i;
+
+ if (i == childCount - 1) {
+ // Draw the selected child last
+ return selectedIndex;
+ } else if (i >= selectedIndex) {
+ // Move the children to the right of the selected child earlier one
+ return i + 1;
+ } else {
+ // Keep the children to the left of the selected child the same
+ return i;
+ }
+ }
+
+ @Override
+ protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+
+ /*
+ * The gallery shows focus by focusing the selected item. So, give
+ * focus to our selected item instead. We steal keys from our
+ * selected item elsewhere.
+ */
+ if (gainFocus && mSelectedChild != null) {
+ mSelectedChild.requestFocus(direction);
+ }
+
+ }
+
+ /**
+ * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to
+ * initiate a fling. Each frame of the fling is handled in {@link #run()}.
+ * A FlingRunnable will keep re-posting itself until the fling is done.
+ *
+ */
+ private class FlingRunnable implements Runnable {
+ /**
+ * Tracks the decay of a fling scroll
+ */
+ private Scroller mScroller;
+
+ /**
+ * X value reported by mScroller on the previous fling
+ */
+ private int mLastFlingX;
+
+ public FlingRunnable() {
+ mScroller = new Scroller(getContext());
+ }
+
+ private void startCommon() {
+ // Remove any pending flings
+ removeCallbacks(this);
+ }
+
+ public void startUsingVelocity(int initialVelocity) {
+ if (initialVelocity == 0) return;
+
+ startCommon();
+
+ int initialX = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
+ mLastFlingX = initialX;
+ mScroller.fling(initialX, 0, initialVelocity, 0,
+ 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
+ post(this);
+ }
+
+ public void startUsingDistance(int distance) {
+ if (distance == 0) return;
+
+ startCommon();
+
+ mLastFlingX = 0;
+ mScroller.startScroll(0, 0, -distance, 0, mAnimationDuration);
+ post(this);
+ }
+
+ public void stop(boolean scrollIntoSlots) {
+ removeCallbacks(this);
+ endFling(scrollIntoSlots);
+ }
+
+ private void endFling(boolean scrollIntoSlots) {
+ /*
+ * Force the scroller's status to finished (without setting its
+ * position to the end)
+ */
+ mScroller.forceFinished(true);
+
+ if (scrollIntoSlots) scrollIntoSlots();
+ }
+
+ public void run() {
+
+ if (mItemCount == 0) {
+ endFling(true);
+ return;
+ }
+
+ mShouldStopFling = false;
+
+ final Scroller scroller = mScroller;
+ boolean more = scroller.computeScrollOffset();
+ final int x = scroller.getCurrX();
+
+ // Flip sign to convert finger direction to list items direction
+ // (e.g. finger moving down means list is moving towards the top)
+ int delta = mLastFlingX - x;
+
+ // Pretend that each frame of a fling scroll is a touch scroll
+ if (delta > 0) {
+ // Moving towards the left. Use first view as mDownTouchPosition
+ mDownTouchPosition = mFirstPosition;
+
+ // Don't fling more than 1 screen
+ delta = Math.min(getWidth() - getPaddingLeft() - getPaddingRight() - 1, delta);
+ } else {
+ // Moving towards the right. Use last view as mDownTouchPosition
+ int offsetToLast = getChildCount() - 1;
+ mDownTouchPosition = mFirstPosition + offsetToLast;
+
+ // Don't fling more than 1 screen
+ delta = Math.max(-(getWidth() - getPaddingRight() - getPaddingLeft() - 1), delta);
+ }
+
+ trackMotionScroll(delta);
+
+ if (more && !mShouldStopFling) {
+ mLastFlingX = x;
+ post(this);
+ } else {
+ endFling(true);
+ }
+ }
+
+ }
+
+ /**
+ * Gallery extends LayoutParams to provide a place to hold current
+ * Transformation information along with previous position/transformation
+ * info.
+ *
+ */
+ public static class LayoutParams extends ViewGroup.LayoutParams {
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ public LayoutParams(int w, int h) {
+ super(w, h);
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+ }
+}