Initial changes to add configurable hotseat.

Change-Id: I4c2ed4a1c122c057662fabc70bfef7c5c088460b
This commit is contained in:
Winson Chung
2011-07-13 17:25:49 -07:00
parent ec8a2eee50
commit 3d503fbd94
33 changed files with 708 additions and 566 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 129 B

+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<com.android.launcher2.Hotseat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:background="@drawable/hotseat_bg_panel"
launcher:cellCountX="1"
launcher:cellCountY="-1">
<com.android.launcher2.CellLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/workspace_top_padding"
android:paddingBottom="@dimen/workspace_bottom_padding"
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
launcher:widthGap="-1dp"
launcher:heightGap="-1dp"
launcher:maxGap="@dimen/workspace_max_gap" />
</com.android.launcher2.Hotseat>
+8 -28
View File
@@ -40,8 +40,8 @@
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal"
android:fadeScrollbars="true"
android:paddingLeft="@dimen/qsb_bar_height"
android:paddingRight="@dimen/button_bar_height"
launcher:defaultScreen="2"
launcher:cellCountX="4"
launcher:cellCountY="4"
@@ -66,31 +66,11 @@
android:layout_height="match_parent"
android:visibility="invisible" />
<RelativeLayout
android:id="@+id/all_apps_button_cluster"
android:layout_height="fill_parent"
android:layout_width="@dimen/button_bar_height_portrait"
android:layout_gravity="right|center_vertical"
android:layout_marginBottom="@dimen/half_status_bar_height">
<ImageView
android:id="@+id/hotseat_left"
style="@style/HotseatButton.Left"
android:layout_below="@id/all_apps_button"
android:src="@drawable/hotseat_phone"
android:onClick="launchHotSeat" />
<com.android.launcher2.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:src="@drawable/all_apps_button"
launcher:direction="vertical" />
<ImageView
android:id="@+id/hotseat_right"
style="@style/HotseatButton.Right"
android:layout_above="@id/all_apps_button"
android:src="@drawable/hotseat_browser"
android:onClick="launchHotSeat" />
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="@dimen/button_bar_height"
android:layout_height="match_parent"
android:layout_gravity="right" />
</RelativeLayout>
</com.android.launcher2.DragLayer>
+3 -1
View File
@@ -26,6 +26,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_search_normal_holo"
android:adjustViewBounds="true"
android:background="@drawable/button_bg"
android:onClick="onClickSearchButton"
android:focusable="true"
@@ -47,9 +48,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_voice_search_holo"
android:adjustViewBounds="true"
android:background="@drawable/button_bg"
android:onClick="onClickVoiceButton"
android:focusable="true"
android:clickable="true"
android:contentDescription="@string/accessibility_voice_search_button" />
</LinearLayout>
</LinearLayout>
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<com.android.launcher2.Hotseat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:background="@drawable/hotseat_bg_panel"
launcher:cellCountX="-1"
launcher:cellCountY="1">
<com.android.launcher2.CellLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/workspace_left_padding"
android:paddingRight="@dimen/workspace_right_padding"
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
launcher:widthGap="-1dp"
launcher:heightGap="-1dp"
launcher:maxGap="@dimen/workspace_max_gap" />
</com.android.launcher2.Hotseat>
+6 -25
View File
@@ -68,31 +68,12 @@
android:layout_height="match_parent"
android:visibility="invisible" />
<RelativeLayout
android:id="@+id/all_apps_button_cluster"
android:layout_width="fill_parent"
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="match_parent"
android:layout_height="@dimen/button_bar_height"
android:layout_gravity="bottom|center_horizontal"
android:paddingTop="2dip">
<ImageView
android:id="@+id/hotseat_left"
style="@style/HotseatButton.Left"
android:layout_toLeftOf="@id/all_apps_button"
android:src="@drawable/hotseat_phone"
android:onClick="launchHotSeat" />
<com.android.launcher2.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:src="@drawable/all_apps_button"
launcher:direction="horizontal" />
<ImageView
android:id="@+id/hotseat_right"
style="@style/HotseatButton.Right"
android:layout_toRightOf="@id/all_apps_button"
android:src="@drawable/hotseat_browser"
android:onClick="launchHotSeat" />
</RelativeLayout>
android:layout_gravity="bottom" />
</com.android.launcher2.DragLayer>
+3 -1
View File
@@ -36,7 +36,8 @@
android:id="@+id/search_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/ic_search_normal_holo" />
android:src="@drawable/ic_search_normal_holo"
android:adjustViewBounds="true" />
</LinearLayout>
<!-- Voice search icon -->
@@ -48,6 +49,7 @@
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic_voice_search_holo"
android:adjustViewBounds="true"
android:background="@drawable/button_bg"
android:onClick="onClickVoiceButton"
android:focusable="true"
+1 -5
View File
@@ -17,7 +17,7 @@
<resources>
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">12dip</dimen>
<dimen name="toolbar_button_horizontal_padding">12dip</dimen>
<dimen name="toolbar_button_horizontal_padding">10dip</dimen>
<!-- Workspace -->
<dimen name="workspace_left_padding">@dimen/qsb_bar_height</dimen>
@@ -28,10 +28,6 @@
<dimen name="scroll_track_padding_left">@dimen/qsb_bar_height</dimen>
<dimen name="scroll_track_padding_right">@dimen/button_bar_height</dimen>
<dimen name="folder_cell_width">100dip</dimen>
<dimen name="folder_cell_height">74dip</dimen>
<dimen name="button_bar_height">62dip</dimen>
<!-- AppsCustomize -->
<dimen name="apps_customize_cell_width">80dp</dimen>
<!-- The width can be 76dp because we don't have B padding -->
+2 -8
View File
@@ -18,16 +18,10 @@
<!-- Workspace -->
<dimen name="workspace_left_padding">0dp</dimen>
<dimen name="workspace_right_padding">0dp</dimen>
<!-- NOTE: This padding is the @dimen/qsb_bar_height + some padding -->
<dimen name="workspace_top_padding">60dp</dimen>
<!-- NOTE: This padding is the @dimen/button_bar_height + some padding
for signposting -->
<dimen name="workspace_bottom_padding">64dp</dimen>
<dimen name="workspace_top_padding">@dimen/qsb_bar_height</dimen>
<dimen name="workspace_bottom_padding">@dimen/button_bar_height</dimen>
<dimen name="workspace_page_spacing">8dp</dimen>
<dimen name="folder_cell_width">74dip</dimen>
<dimen name="folder_cell_height">86dip</dimen>
<integer name="apps_customize_cellCountX">4</integer>
<integer name="apps_customize_cellCountY">5</integer>
<dimen name="apps_customize_pageLayoutWidthGap">-1dp</dimen>
+10
View File
@@ -38,6 +38,15 @@
<attr name="cellCountY" format="integer" />
</declare-styleable>
<!-- Hotseat specific attributes. These attributes are used to customize
the hotseat in XML files. -->
<declare-styleable name="Hotseat">
<!-- The number of horizontal cells in the CellLayout -->
<attr name="cellCountX" />
<!-- The number of vertical cells in the CellLayout -->
<attr name="cellCountY" />
</declare-styleable>
<!-- CellLayout specific attributes. These attributes are used to customize
a CellLayout view in XML files. -->
<declare-styleable name="CellLayout">
@@ -125,6 +134,7 @@
<declare-styleable name="Favorite">
<attr name="className" format="string" />
<attr name="packageName" format="string" />
<attr name="container" format="string" />
<attr name="screen" format="string" />
<attr name="x" format="string" />
<attr name="y" format="string" />
+3 -3
View File
@@ -16,7 +16,7 @@
<resources>
<!-- Workspace -->
<dimen name="qsb_bar_height">56dp</dimen>
<dimen name="qsb_bar_height">48dp</dimen>
<dimen name="workspace_cell_width">80dp</dimen>
<dimen name="workspace_cell_height">80dp</dimen>
<dimen name="workspace_width_gap">-1dp</dimen>
@@ -42,14 +42,14 @@
<dimen name="title_texture_width">120px</dimen>
<!-- height of the bottom row of controls -->
<dimen name="button_bar_height">56dip</dimen>
<dimen name="button_bar_height">80dip</dimen>
<!-- Drag padding to add to the drop targets -->
<dimen name="drop_target_drag_padding">20dp</dimen>
<!-- so we have access to this dimension in landscape mode even though
button_bar_height changes -->
<dimen name="button_bar_height_portrait">56dip</dimen>
<dimen name="button_bar_height_portrait">80dip</dimen>
<!-- extra horizontal spacing between mini screen thumbnails ie. in all
apps and in customization mode -->
+2
View File
@@ -120,6 +120,8 @@
<string name="add_photo_frame">Picture frame</string>
<!-- Error message when user has filled a home screen, possibly not used -->
<string name="out_of_space">No more room on this Home screen.</string>
<!-- Error message when user tries to drop an invalid item on the hotseat -->
<string name="invalid_hotseat_item">This widget is too large for the hotseat.</string>
<!-- Message displayed when a shortcut is created by an external application -->
<string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string>
<!-- Message displayed when a shortcut is uninstalled by an external application -->
+35 -6
View File
@@ -15,13 +15,19 @@
-->
<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
<!-- Far-left screen [0] -->
<!-- Far-left screen [0] -->
<!-- Left screen [1] -->
<!-- Middle screen [2] -->
<!-- Left screen [1] -->
<!-- Right screen [3] -->
<!-- Middle screen [2] -->
<favorite
launcher:packageName="com.google.android.camera"
launcher:className="com.android.camera.Camera"
launcher:screen="2"
launcher:x="0"
launcher:y="3" />
<!-- Right screen [3] -->
<appwidget
launcher:packageName="com.android.music"
launcher:className="com.android.music.MediaAppWidgetProvider"
@@ -31,6 +37,29 @@
launcher:spanX="4"
launcher:spanY="1" />
<!-- Far-right screen [4] -->
<!-- Far-right screen [4] -->
<!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
<favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.DialtactsActivity"
launcher:container="-101"
launcher:screen="1"
launcher:x="0"
launcher:y="0" />
<favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.PeopleActivity"
launcher:container="-101"
launcher:screen="2"
launcher:x="0"
launcher:y="0" />
<favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
launcher:screen="3"
launcher:x="0"
launcher:y="0" />
</favorites>
@@ -1863,6 +1863,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
int spanX;
int spanY;
int screen;
long container;
boolean valid;
@Override
+6 -6
View File
@@ -41,13 +41,13 @@ class ButtonBarKeyEventListener implements View.OnKeyListener {
}
/**
* A keyboard listener we set on all the dock buttons.
* A keyboard listener we set on all the hotseat buttons.
*/
class DockKeyEventListener implements View.OnKeyListener {
class HotseatKeyEventListener implements View.OnKeyListener {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
final Configuration configuration = v.getResources().getConfiguration();
return FocusHelper.handleDockButtonKeyEvent(v, keyCode, event, configuration.orientation);
return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation);
}
}
@@ -535,9 +535,9 @@ public class FocusHelper {
}
/**
* Handles key events in the workspace dock (bottom of the screen).
* Handles key events in the workspace hotseat (bottom of the screen).
*/
static boolean handleDockButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
final ViewGroup parent = (ViewGroup) v.getParent();
final ViewGroup launcher = (ViewGroup) parent.getParent();
final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
@@ -547,7 +547,7 @@ public class FocusHelper {
final int pageCount = workspace.getChildCount();
// NOTE: currently we don't special case for the phone UI in different
// orientations, even though the dock is on the side in landscape mode. This
// orientations, even though the hotseat is on the side in landscape mode. This
// is to ensure that accessibility consistency is maintained across rotations.
final int action = e.getAction();
+6 -9
View File
@@ -732,8 +732,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int centeredTop = centerY - height / 2;
// We first fetch the currently visible CellLayoutChildren
int page = mLauncher.getWorkspace().getCurrentPage();
CellLayout currentPage = (CellLayout) mLauncher.getWorkspace().getChildAt(page);
CellLayout currentPage = mLauncher.getWorkspace().getCurrentDropLayout();
CellLayoutChildren boundingLayout = currentPage.getChildrenLayout();
Rect bounds = new Rect();
parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
@@ -851,8 +850,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
// Remove the folder completely
final CellLayout cellLayout = (CellLayout)
mLauncher.getWorkspace().getChildAt(mInfo.screen);
CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
cellLayout.removeView(mFolderIcon);
if (mFolderIcon instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) mFolderIcon);
@@ -860,9 +858,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mLauncher.removeFolder(mInfo);
if (finalItem != null) {
LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem,
LauncherSettings.Favorites.CONTAINER_DESKTOP, mInfo.screen,
mInfo.cellX, mInfo.cellY);
LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
mInfo.screen, mInfo.cellX, mInfo.cellY);
}
LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
@@ -871,8 +868,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
View child = mLauncher.createShortcut(R.layout.application, cellLayout,
(ShortcutInfo) finalItem);
mLauncher.getWorkspace().addInScreen(child, mInfo.screen, mInfo.cellX, mInfo.cellY,
mInfo.spanX, mInfo.spanY);
mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen, mInfo.cellX,
mInfo.cellY, mInfo.spanX, mInfo.spanY);
}
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2011 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.android.launcher2;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import com.android.launcher.R;
public class Hotseat extends FrameLayout {
static final String TAG = "Hotseat";
private Launcher mLauncher;
private CellLayout mContent;
private int mCellCountX;
private int mCellCountY;
private boolean mIsLandscape;
public Hotseat(Context context) {
this(context, null);
}
public Hotseat(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Hotseat, defStyle, 0);
mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1);
mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1);
mIsLandscape = context.getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE;
}
public void setup(Launcher launcher) {
mLauncher = launcher;
}
CellLayout getLayout() {
return mContent;
}
/* Get the orientation invariant order of the item in the hotseat for persistence. */
int getOrderInHotseat(int x, int y) {
return mIsLandscape ? (mContent.getCountY() - y - 1) : x;
}
/* Get the orientation specific coordinates given an invariant order in the hotseat. */
int getCellXFromOrder(int rank) {
return mIsLandscape ? 0 : rank;
}
int getCellYFromOrder(int rank) {
return mIsLandscape ? (mContent.getCountY() - (rank + 1)) : 0;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mCellCountX < 0) mCellCountX = LauncherModel.getCellCountX();
if (mCellCountY < 0) mCellCountY = LauncherModel.getCellCountY();
mContent = (CellLayout) findViewById(R.id.layout);
mContent.setGridSize(mCellCountX, mCellCountY);
resetLayout();
}
void resetLayout() {
mContent.removeAllViewsInLayout();
// Add the Apps button
Context context = getContext();
LayoutInflater inflater = LayoutInflater.from(context);
BubbleTextView allAppsButton = (BubbleTextView)
inflater.inflate(R.layout.application, mContent, false);
allAppsButton.setCompoundDrawablesWithIntrinsicBounds(null,
context.getResources().getDrawable(R.drawable.apps_hotseat_button), null, null);
// button.setText(context.getString(R.string.all_apps_button_label));
allAppsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(android.view.View v) {
mLauncher.showAllApps(true);
}
});
// Note: We do this to ensure that the hotseat is always laid out in the orientation of
// the hotseat in order regardless of which orientation they were added
int x = getCellXFromOrder(0);
int y = getCellYFromOrder(0);
mContent.addViewToCellLayout(allAppsButton, -1, 0, new CellLayout.LayoutParams(x,y,1,1),
true);
}
}
@@ -65,7 +65,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
LauncherApplication app = (LauncherApplication) context.getApplicationContext();
app.getModel().addShortcut(context, data, screen, mCoordinates[0],
app.getModel().addShortcut(context, data,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],
mCoordinates[1], true);
Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
Toast.LENGTH_SHORT).show();
@@ -94,14 +95,16 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
int cellX, cellY, spanX, spanY;
for (int i = 0; i < items.size(); ++i) {
item = items.get(i);
if (item.screen == screen) {
cellX = item.cellX;
cellY = item.cellY;
spanX = item.spanX;
spanY = item.spanY;
for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
occupied[x][y] = true;
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (item.screen == screen) {
cellX = item.cellX;
cellY = item.cellY;
spanX = item.spanX;
spanY = item.spanY;
for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
occupied[x][y] = true;
}
}
}
}
@@ -188,7 +188,8 @@ public class InstallWidgetReceiver {
final PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo(widgetInfo, mMimeType,
mClipData);
mLauncher.addAppWidgetFromDrop(createInfo, mTargetLayoutScreen, null, mTargetLayoutPos);
mLauncher.addAppWidgetFromDrop(createInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP,
mTargetLayoutScreen, null, mTargetLayoutPos);
}
}
}
+139 -324
View File
@@ -115,7 +115,6 @@ public final class Launcher extends Activity
static final boolean PROFILE_STARTUP = false;
static final boolean DEBUG_WIDGETS = false;
static final boolean DEBUG_USER_INTERFACE = false;
private static final int MENU_GROUP_ADD = 1;
private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
@@ -149,6 +148,8 @@ public final class Launcher extends Activity
// Type: int
private static final String RUNTIME_STATE = "launcher.state";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_CONTAINER = "launcher.add_container";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
@@ -185,16 +186,14 @@ public final class Launcher extends Activity
private AppWidgetManager mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
private int mAddScreen = -1;
private int mAddCellX = -1;
private int mAddCellY = -1;
private int[] mAddDropPosition;
private ItemInfo mPendingAddInfo = new ItemInfo();
private int[] mTmpAddItemCellCoordinates = new int[2];
private FolderInfo mFolderInfo;
private ViewGroup mButtonCluster;
private Hotseat mHotseat;
private View mAllAppsButton;
private SearchDropTargetBar mSearchDeleteBar;
private AppsCustomizeTabHost mAppsCustomizeTabHost;
private AppsCustomizePagedView mAppsCustomizeContent;
@@ -259,6 +258,7 @@ public final class Launcher extends Activity
private static class PendingAddArguments {
int requestCode;
Intent intent;
long container;
int screen;
int cellX;
int cellY;
@@ -600,20 +600,22 @@ public final class Launcher extends Activity
private boolean completeAdd(PendingAddArguments args) {
switch (args.requestCode) {
case REQUEST_PICK_APPLICATION:
completeAddApplication(args.intent, args.screen, args.cellX, args.cellY);
completeAddApplication(args.intent, args.container, args.screen, args.cellX,
args.cellY);
break;
case REQUEST_PICK_SHORTCUT:
processShortcut(args.intent);
break;
case REQUEST_CREATE_SHORTCUT:
completeAddShortcut(args.intent, args.screen, args.cellX, args.cellY);
completeAddShortcut(args.intent, args.container, args.screen, args.cellX,
args.cellY);
return true;
case REQUEST_PICK_APPWIDGET:
addAppWidgetFromPick(args.intent);
break;
case REQUEST_CREATE_APPWIDGET:
int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
completeAddAppWidget(appWidgetId, args.screen);
completeAddAppWidget(appWidgetId, args.container, args.screen);
return true;
case REQUEST_PICK_WALLPAPER:
// We just wanted the activity result here so we can clear mWaitingForResult
@@ -632,13 +634,15 @@ public final class Launcher extends Activity
// For example, the user would PICK_SHORTCUT for "Music playlist", and we
// launch over to the Music app to actually CREATE_SHORTCUT.
if (resultCode == RESULT_OK && mAddScreen != -1) {
if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID &&
mPendingAddInfo.screen > -1) {
final PendingAddArguments args = new PendingAddArguments();
args.requestCode = requestCode;
args.intent = data;
args.screen = mAddScreen;
args.cellX = mAddCellX;
args.cellY = mAddCellY;
args.container = mPendingAddInfo.container;
args.screen = mPendingAddInfo.screen;
args.cellX = mPendingAddInfo.cellX;
args.cellY = mPendingAddInfo.cellY;
// If the loader is still running, defer the add until it is done.
if (isWorkspaceLocked()) {
@@ -797,12 +801,15 @@ public final class Launcher extends Activity
mWorkspace.setCurrentPage(currentScreen);
}
final int addScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
final long pendingAddContainer = savedState.getLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, -1);
final int pendingAddScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
if (addScreen > -1) {
mAddScreen = addScreen;
mAddCellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
mAddCellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
if (pendingAddContainer != ItemInfo.NO_ID && pendingAddScreen > -1) {
mPendingAddInfo.container = pendingAddContainer;
mPendingAddInfo.screen = pendingAddScreen;
mPendingAddInfo.cellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
mRestoring = true;
}
@@ -841,6 +848,12 @@ public final class Launcher extends Activity
// 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);
mWorkspace.setOnLongClickListener(this);
@@ -857,47 +870,9 @@ public final class Launcher extends Activity
mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
mAppsCustomizeContent.setup(this, dragController);
// Setup AppsCustomize button
mAllAppsButton = mDragLayer.findViewById(R.id.all_apps_button);
mAllAppsButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
onClickAllAppsButton(v);
}
});
if (!LauncherApplication.isScreenLarge()) {
// Setup AppsCustomize button on the phone
HandleView handleView = (HandleView) mAllAppsButton;
handleView.setLauncher(this);
handleView.setOnLongClickListener(this);
// Setup Hotseat
ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
hotseatLeft.setContentDescription(mHotseatLabels[0]);
hotseatLeft.setImageDrawable(mHotseatIcons[0]);
ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
hotseatRight.setContentDescription(mHotseatLabels[1]);
hotseatRight.setImageDrawable(mHotseatIcons[1]);
}
if (!LauncherApplication.isScreenLarge()) {
// Setup keylistener for button cluster
mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
View.OnKeyListener listener = null;
if (LauncherApplication.isScreenLarge()) {
// For tablets, AllApps lives in the button bar at the top
listener = new ButtonBarKeyEventListener();
} else {
// For phones, AppsCustomize lives in the "dock" at the bottom
listener = new DockKeyEventListener();
}
int buttonCount = mButtonCluster.getChildCount();
for (int i = 0; i < buttonCount; ++i) {
mButtonCluster.getChildAt(i).setOnKeyListener(listener);
}
}
// Setup the drag controller (the drop targets have to be added in reverse order)
// Setup the drag controller (drop targets have to be added in reverse order in priority)
dragController.setDragScoller(mWorkspace);
dragController.setScrollView(mDragLayer);
dragController.setMoveTarget(mWorkspace);
@@ -907,40 +882,7 @@ public final class Launcher extends Activity
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void previousScreen(View v) {
if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.scrollLeft();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void nextScreen(View v) {
if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.scrollRight();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void launchHotSeat(View v) {
if (mState == State.APPS_CUSTOMIZE) return;
int index = -1;
if (v.getId() == R.id.hotseat_left) {
index = 0;
} else if (v.getId() == R.id.hotseat_right) {
index = 1;
}
// reload these every tap; you never know when they might change
loadHotseats();
if (index >= 0 && index < mHotseats.length && mHotseats[index] != null) {
startActivitySafely(
mHotseats[index],
"hotseat"
);
}
}
/**
* Creates a view representing a shortcut.
@@ -976,9 +918,9 @@ public final class Launcher extends Activity
* @param data The intent describing the application.
* @param cellInfo The position on screen where to create the shortcut.
*/
void completeAddApplication(Intent data, int screen, int cellX, int cellY) {
void completeAddApplication(Intent data, long container, int screen, int cellX, int cellY) {
final int[] cellXY = mTmpAddItemCellCoordinates;
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
final CellLayout layout = getCellLayout(container, screen);
// First we check if we already know the exact location where we want to add this item.
if (cellX >= 0 && cellY >= 0) {
@@ -995,7 +937,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, screen, cellXY[0], cellXY[1],
mWorkspace.addApplicationShortcut(info, layout, container, screen, cellXY[0], cellXY[1],
isWorkspaceLocked(), cellX, cellY);
} else {
Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
@@ -1008,11 +950,12 @@ public final class Launcher extends Activity
* @param data The intent describing the shortcut.
* @param cellInfo The position on screen where to create the shortcut.
*/
private void completeAddShortcut(Intent data, int screen, int cellX, int cellY) {
final int[] cellXY = mTmpAddItemCellCoordinates;
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
private void completeAddShortcut(Intent data, long container, int screen, int cellX,
int cellY) {
int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mPendingAddInfo.dropPos;
CellLayout layout = getCellLayout(container, screen);
int[] touchXY = mAddDropPosition;
boolean foundCellSpan = false;
// First we check if we already know the exact location where we want to add this item.
@@ -1022,9 +965,7 @@ public final class Launcher extends Activity
foundCellSpan = true;
} else if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
int[] result = screenLayout.findNearestVacantArea(
touchXY[0], touchXY[1], 1, 1, cellXY);
int[] result = layout.findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, cellXY);
foundCellSpan = (result != null);
} else {
foundCellSpan = layout.findCellForSpan(cellXY, 1, 1);
@@ -1036,11 +977,12 @@ public final class Launcher extends Activity
}
final ShortcutInfo info = mModel.addShortcut(
this, data, screen, cellXY[0], cellXY[1], false);
this, data, container, screen, cellXY[0], cellXY[1], false);
if (!mRestoring) {
final View view = createShortcut(info);
mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
mWorkspace.addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1,
isWorkspaceLocked());
}
}
@@ -1050,11 +992,11 @@ public final class Launcher extends Activity
* @param appWidgetId The app widget id
* @param cellInfo The position on screen where to create the widget.
*/
private void completeAddAppWidget(final int appWidgetId, int screen) {
private void completeAddAppWidget(final int appWidgetId, long container, int screen) {
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
// Calculate the grid spans needed to fit this widget
CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
CellLayout layout = getCellLayout(container, screen);
// We want to account for the extra amount of padding that we are adding to the widget
// to ensure that it gets the full amount of space that it has requested
@@ -1070,18 +1012,16 @@ public final class Launcher extends Activity
// Try finding open space on Launcher screen
// We have saved the position to which the widget was dragged-- this really only matters
// if we are placing widgets on a "spring-loaded" screen
final int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mAddDropPosition;
int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mPendingAddInfo.dropPos;
boolean foundCellSpan = false;
if (mAddCellX >= 0 && mAddCellY >= 0) {
cellXY[0] = mAddCellX;
cellXY[1] = mAddCellY;
if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
cellXY[0] = mPendingAddInfo.cellX;
cellXY[1] = mPendingAddInfo.cellY;
foundCellSpan = true;
} else if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
int[] result = screenLayout.findNearestVacantArea(
int[] result = layout.findNearestVacantArea(
touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
foundCellSpan = (result != null);
} else {
@@ -1108,8 +1048,7 @@ public final class Launcher extends Activity
launcherInfo.spanY = spanXY[1];
LauncherModel.addItemToDatabase(this, launcherInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screen, cellXY[0], cellXY[1], false);
container, screen, cellXY[0], cellXY[1], false);
if (!mRestoring) {
// Perform actual inflation because we're live
@@ -1118,7 +1057,7 @@ public final class Launcher extends Activity
launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
launcherInfo.hostView.setTag(launcherInfo);
mWorkspace.addInScreen(launcherInfo.hostView, screen, cellXY[0], cellXY[1],
mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
@@ -1331,10 +1270,12 @@ public final class Launcher extends Activity
// this state is reflected.
closeFolder();
if (mAddScreen > -1 && mWaitingForResult) {
outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mAddScreen);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mAddCellX);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mAddCellY);
if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screen > -1 &&
mWaitingForResult) {
outState.putLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, mPendingAddInfo.container);
outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mPendingAddInfo.screen);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mPendingAddInfo.cellX);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mPendingAddInfo.cellY);
}
if (mFolderInfo != null && mWaitingForResult) {
@@ -1372,7 +1313,7 @@ public final class Launcher extends Activity
TextKeyListener.getInstance().release();
unbindWorkspaceItems();
unbindWorkspaceAndHotseatItems();
getContentResolver().unregisterContentObserver(mWidgetObserver);
unregisterReceiver(mCloseSystemDialogsReceiver);
@@ -1507,10 +1448,11 @@ public final class Launcher extends Activity
}
private void resetAddInfo() {
mAddScreen = -1;
mAddCellX = -1;
mAddCellY = -1;
mAddDropPosition = null;
mPendingAddInfo.container = ItemInfo.NO_ID;
mPendingAddInfo.screen = -1;
mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
mPendingAddInfo.dropPos = null;
}
private void manageApps() {
@@ -1566,7 +1508,7 @@ public final class Launcher extends Activity
startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise just add it
completeAddAppWidget(appWidgetId, mAddScreen);
completeAddAppWidget(appWidgetId, info.container, info.screen);
// Exit spring loaded mode if necessary after adding the widget
exitSpringLoadedDragModeDelayed(false);
@@ -1581,14 +1523,16 @@ public final class Launcher extends Activity
* @param cell The cell it should be added to, optional
* @param position The location on the screen where it was dropped, optional
*/
void processShortcutFromDrop(ComponentName componentName, int screen, int[] cell, int[] loc) {
void processShortcutFromDrop(ComponentName componentName, long container, int screen,
int[] cell, int[] loc) {
resetAddInfo();
mAddScreen = screen;
mAddDropPosition = loc;
mPendingAddInfo.container = container;
mPendingAddInfo.screen = screen;
mPendingAddInfo.dropPos = loc;
if (cell != null) {
mAddCellX = cell[0];
mAddCellY = cell[1];
mPendingAddInfo.cellX = cell[0];
mPendingAddInfo.cellY = cell[1];
}
Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
@@ -1604,14 +1548,15 @@ public final class Launcher extends Activity
* @param cell The cell it should be added to, optional
* @param position The location on the screen where it was dropped, optional
*/
void addAppWidgetFromDrop(PendingAddWidgetInfo info, int screen, int[] cell, int[] loc) {
void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, int screen,
int[] cell, int[] loc) {
resetAddInfo();
mAddScreen = screen;
mAddDropPosition = loc;
mPendingAddInfo.container = info.container = container;
mPendingAddInfo.screen = info.screen = screen;
mPendingAddInfo.dropPos = loc;
if (cell != null) {
mAddCellX = cell[0];
mAddCellY = cell[1];
mPendingAddInfo.cellX = cell[0];
mPendingAddInfo.cellY = cell[1];
}
int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
@@ -1641,21 +1586,21 @@ public final class Launcher extends Activity
startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
}
FolderIcon addFolder(final int screen, int cellX, int cellY) {
FolderIcon addFolder(CellLayout layout, long container, final int screen, int cellX,
int cellY) {
final FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
// Update the model
LauncherModel.addItemToDatabase(Launcher.this, folderInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screen, cellX, cellY, false);
LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screen, cellX, cellY,
false);
sFolders.put(folderInfo.id, folderInfo);
// Create the view
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, screen, cellX, cellY, 1, 1, isWorkspaceLocked());
FolderIcon newFolder =
FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, container, screen, cellX, cellY, 1, 1,
isWorkspaceLocked());
return newFolder;
}
@@ -1753,8 +1698,7 @@ public final class Launcher extends Activity
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
CellLayout cl = (CellLayout) mWorkspace.getChildAt(folder.mInfo.screen);
FolderIcon fi = (FolderIcon) cl.getChildAt(folder.mInfo.cellX, folder.mInfo.cellY);
FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
shrinkAndFadeInFolderIcon(fi);
mDragController.removeDropTarget((DropTarget)folder);
}
@@ -1774,7 +1718,7 @@ public final class Launcher extends Activity
* Go through the and disconnect any of the callbacks in the drawables and the views or we
* leak the previous Home screen on orientation change.
*/
private void unbindWorkspaceItems() {
private void unbindWorkspaceAndHotseatItems() {
LauncherModel.unbindWorkspaceItems();
}
@@ -1995,16 +1939,6 @@ public final class Launcher extends Activity
return false;
}
switch (v.getId()) {
case R.id.all_apps_button:
if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
}
return true;
}
if (isWorkspaceLocked()) {
return false;
}
@@ -2020,12 +1954,13 @@ public final class Launcher extends Activity
return true;
}
// The hotseat touch handling does not go through Workspace, and we always allow long press
// on hotseat items.
final View itemUnderLongClick = longClickCellInfo.cell;
if (mWorkspace.allowLongPress() && !mDragController.isDragging()) {
boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();
if (allowLongPress && !mDragController.isDragging()) {
if (itemUnderLongClick == null) {
// User long pressed on empty space
mWorkspace.setAllowLongPress(false);
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
addItems();
@@ -2041,137 +1976,26 @@ public final class Launcher extends Activity
return true;
}
@SuppressWarnings({"unchecked"})
private void dismissPreview(final View v) {
final PopupWindow window = (PopupWindow) v.getTag();
if (window != null) {
window.setOnDismissListener(new PopupWindow.OnDismissListener() {
public void onDismiss() {
ViewGroup group = (ViewGroup) v.getTag(R.id.workspace);
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
((ImageView) group.getChildAt(i)).setImageDrawable(null);
}
ArrayList<Bitmap> bitmaps =
(ArrayList<Bitmap>) v.getTag(R.id.all_apps_button_cluster);
for (Bitmap bitmap : bitmaps) bitmap.recycle();
v.setTag(R.id.workspace, null);
v.setTag(R.id.all_apps_button_cluster, null);
window.setOnDismissListener(null);
}
});
window.dismiss();
}
v.setTag(null);
boolean isHotseatLayout(View layout) {
return mHotseat != null && layout != null &&
(layout instanceof CellLayout) && (layout == mHotseat.getLayout());
}
Hotseat getHotseat() {
return mHotseat;
}
private void showPreviews(View anchor) {
showPreviews(anchor, 0, mWorkspace.getChildCount());
}
private void showPreviews(final View anchor, int start, int end) {
final Resources resources = getResources();
final Workspace workspace = mWorkspace;
CellLayout cell = ((CellLayout) workspace.getChildAt(start));
float max = workspace.getChildCount();
final Rect r = new Rect();
resources.getDrawable(R.drawable.preview_background).getPadding(r);
int extraW = (int) ((r.left + r.right) * max);
int extraH = r.top + r.bottom;
int aW = cell.getWidth() - extraW;
float w = aW / max;
int width = cell.getWidth();
int height = cell.getHeight();
int x = cell.getPaddingLeft();
int y = cell.getPaddingTop();
width -= (x + cell.getPaddingRight());
height -= (y + cell.getPaddingBottom());
float scale = w / width;
int count = end - start;
final float sWidth = width * scale;
float sHeight = height * scale;
LinearLayout preview = new LinearLayout(this);
PreviewTouchHandler handler = new PreviewTouchHandler(anchor);
ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>(count);
for (int i = start; i < end; i++) {
ImageView image = new ImageView(this);
cell = (CellLayout) workspace.getChildAt(i);
final Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(bitmap);
c.scale(scale, scale);
c.translate(-cell.getPaddingLeft(), -cell.getPaddingTop());
cell.drawChildren(c);
image.setBackgroundDrawable(resources.getDrawable(R.drawable.preview_background));
image.setImageBitmap(bitmap);
image.setTag(i);
image.setOnClickListener(handler);
image.setOnFocusChangeListener(handler);
image.setFocusable(true);
if (i == mWorkspace.getCurrentPage()) image.requestFocus();
preview.addView(image,
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
bitmaps.add(bitmap);
}
final PopupWindow p = new PopupWindow(this);
p.setContentView(preview);
p.setWidth((int) (sWidth * count + extraW));
p.setHeight((int) (sHeight + extraH));
p.setAnimationStyle(R.style.AnimationPreview);
p.setOutsideTouchable(true);
p.setFocusable(true);
p.setBackgroundDrawable(new ColorDrawable(0));
p.showAsDropDown(anchor, 0, 0);
p.setOnDismissListener(new PopupWindow.OnDismissListener() {
public void onDismiss() {
dismissPreview(anchor);
}
});
anchor.setTag(p);
anchor.setTag(R.id.workspace, preview);
anchor.setTag(R.id.all_apps_button_cluster, bitmaps);
}
class PreviewTouchHandler implements View.OnClickListener, Runnable, View.OnFocusChangeListener {
private final View mAnchor;
public PreviewTouchHandler(View anchor) {
mAnchor = anchor;
}
public void onClick(View v) {
mWorkspace.snapToPage((Integer) v.getTag());
v.post(this);
}
public void run() {
dismissPreview(mAnchor);
}
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
mWorkspace.snapToPage((Integer) v.getTag());
/**
* Returns the CellLayout of the specified container at the specified screen.
*/
CellLayout getCellLayout(long container, int screen) {
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
if (mHotseat != null) {
return mHotseat.getLayout();
} else {
return null;
}
} else {
return (CellLayout) mWorkspace.getChildAt(screen);
}
}
@@ -2215,7 +2039,8 @@ public final class Launcher extends Activity
private void showAddDialog() {
resetAddInfo();
mAddScreen = mWorkspace.getCurrentPage();
mPendingAddInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
mPendingAddInfo.screen = mWorkspace.getCurrentPage();
mWaitingForResult = true;
showDialog(DIALOG_CREATE_SHORTCUT);
}
@@ -2594,29 +2419,29 @@ public final class Launcher extends Activity
}
/**
* Shows the dock/hotseat area.
* Shows the hotseat area.
*/
void showDock(boolean animated) {
void showHotseat(boolean animated) {
if (!LauncherApplication.isScreenLarge()) {
if (animated) {
int duration = mSearchDeleteBar.getTransitionInDuration();
mButtonCluster.animate().alpha(1f).setDuration(duration);
mHotseat.animate().alpha(1f).setDuration(duration);
} else {
mButtonCluster.setAlpha(1f);
mHotseat.setAlpha(1f);
}
}
}
/**
* Hides the dock/hotseat area.
* Hides the hotseat area.
*/
void hideDock(boolean animated) {
void hideHotseat(boolean animated) {
if (!LauncherApplication.isScreenLarge()) {
if (animated) {
int duration = mSearchDeleteBar.getTransitionOutDuration();
mButtonCluster.animate().alpha(0f).setDuration(duration);
mHotseat.animate().alpha(0f).setDuration(duration);
} else {
mButtonCluster.setAlpha(0f);
mHotseat.setAlpha(0f);
}
}
}
@@ -2627,9 +2452,9 @@ public final class Launcher extends Activity
cameraZoomOut(State.APPS_CUSTOMIZE, animated, false);
mAppsCustomizeTabHost.requestFocus();
// Hide the search bar and dock
// Hide the search bar and hotseat
mSearchDeleteBar.hideSearchBar(animated);
hideDock(animated);
hideHotseat(animated);
// Change the state *after* we've called all the transition code
mState = State.APPS_CUSTOMIZE;
@@ -2686,12 +2511,14 @@ public final class Launcher extends Activity
mWorkspace.setVisibility(View.VISIBLE);
cameraZoomIn(State.APPS_CUSTOMIZE, animated, false);
// Show the search bar and dock
// Show the search bar and hotseat
mSearchDeleteBar.showSearchBar(animated);
showDock(animated);
showHotseat(animated);
// Set focus to the AppsCustomize button
findViewById(R.id.all_apps_button).requestFocus();
if (mAllAppsButton != null) {
mAllAppsButton.requestFocus();
}
}
}
@@ -3024,21 +2851,12 @@ public final class Launcher extends Activity
final CellLayout layoutParent = (CellLayout) workspace.getChildAt(i);
layoutParent.removeAllViewsInLayout();
}
if (DEBUG_USER_INTERFACE) {
android.widget.Button finishButton = new android.widget.Button(this);
finishButton.setText("Finish");
workspace.addInScreen(finishButton, 1, 0, 0, 1, 1);
finishButton.setOnClickListener(new android.widget.Button.OnClickListener() {
public void onClick(View v) {
finish();
}
});
if (mHotseat != null) {
mHotseat.resetLayout();
}
// This wasn't being called before which resulted in a leak of AppWidgetHostViews
unbindWorkspaceItems();
unbindWorkspaceAndHotseatItems();
}
/**
@@ -3047,30 +2865,27 @@ public final class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
setLoadOnResume();
final Workspace workspace = mWorkspace;
for (int i=start; i<end; i++) {
final ItemInfo item = shortcuts.get(i);
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
final View shortcut = createShortcut((ShortcutInfo)item);
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
false);
View shortcut = createShortcut((ShortcutInfo)item);
workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
item.cellY, 1, 1, false);
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(FolderInfo) item, mIconCache);
workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
false);
workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,
item.cellY, 1, 1, false);
break;
}
}
workspace.requestLayout();
}
@@ -3108,7 +2923,7 @@ public final class Launcher extends Activity
item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
item.hostView.setTag(item);
workspace.addInScreen(item.hostView, item.screen, item.cellX,
workspace.addInScreen(item.hostView, item.container, item.screen, item.cellX,
item.cellY, item.spanX, item.spanY, false);
addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
+36 -22
View File
@@ -178,17 +178,24 @@ public class LauncherModel extends BroadcastReceiver {
static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
final int screen, final int cellX, final int cellY) {
item.container = container;
item.screen = screen;
item.cellX = cellX;
item.cellY = cellY;
// We store hotseat items in canonical form which is this orientation invariant position
// in the hotseat
if (context instanceof Launcher && screen < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
} else {
item.screen = screen;
}
final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
values.put(LauncherSettings.Favorites.CONTAINER, item.container);
values.put(LauncherSettings.Favorites.CELLX, cellX);
values.put(LauncherSettings.Favorites.CELLY, cellY);
values.put(LauncherSettings.Favorites.CELLX, item.cellX);
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
values.put(LauncherSettings.Favorites.SCREEN, item.screen);
sWorker.post(new Runnable() {
@@ -205,7 +212,8 @@ public class LauncherModel extends BroadcastReceiver {
// Items are added/removed from the corresponding FolderInfo elsewhere, such
// as in Workspace.onDrop. Here, we just add/remove them from the list of items
// that are on the desktop, as appropriate
if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
if (!sWorkspaceItems.contains(modelItem)) {
sWorkspaceItems.add(modelItem);
}
@@ -356,12 +364,19 @@ public class LauncherModel extends BroadcastReceiver {
* Add an item to the database in a specified container. Sets the container, screen, cellX and
* cellY fields of the item. Also assigns an ID to the item.
*/
static void addItemToDatabase(Context context, final ItemInfo item, long container,
int screen, int cellX, int cellY, final boolean notify) {
static void addItemToDatabase(Context context, final ItemInfo item, final long container,
final int screen, final int cellX, final int cellY, final boolean notify) {
item.container = container;
item.screen = screen;
item.cellX = cellX;
item.cellY = cellY;
// We store hotseat items in canonical form which is this orientation invariant position
// in the hotseat
if (context instanceof Launcher && screen < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
} else {
item.screen = screen;
}
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
@@ -371,7 +386,7 @@ public class LauncherModel extends BroadcastReceiver {
LauncherApplication app = (LauncherApplication) l.getApplication();
item.id = app.getLauncherProvider().generateNewId();
values.put(LauncherSettings.Favorites._ID, item.id);
item.updateValuesWithCoordinates(values, cellX, cellY);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
sWorker.post(new Runnable() {
public void run() {
@@ -382,13 +397,11 @@ public class LauncherModel extends BroadcastReceiver {
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
sFolders.put(item.id, (FolderInfo) item);
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
sWorkspaceItems.add(item);
}
break;
// Fall through
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
sWorkspaceItems.add(item);
}
break;
@@ -404,8 +417,8 @@ public class LauncherModel extends BroadcastReceiver {
* Creates a new unique child id, for a given cell span across all layouts.
*/
static int getCellLayoutChildId(
int cellId, int screen, int localCellX, int localCellY, int spanX, int spanY) {
return ((cellId & 0xFF) << 24)
long container, int screen, int localCellX, int localCellY, int spanX, int spanY) {
return (((int) container & 0xFF) << 24)
| (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
}
@@ -928,6 +941,7 @@ public class LauncherModel extends BroadcastReceiver {
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
sWorkspaceItems.add(info);
break;
default:
@@ -972,6 +986,7 @@ public class LauncherModel extends BroadcastReceiver {
}
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
sWorkspaceItems.add(folderInfo);
break;
}
@@ -1003,9 +1018,10 @@ public class LauncherModel extends BroadcastReceiver {
appWidgetInfo.spanY = c.getInt(spanYIndex);
container = c.getInt(containerIndex);
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
Log.e(TAG, "Widget found where container "
+ "!= CONTAINER_DESKTOP -- ignoring!");
+ "!= CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
continue;
}
appWidgetInfo.container = c.getInt(containerIndex);
@@ -1607,12 +1623,10 @@ public class LauncherModel extends BroadcastReceiver {
}
}
ShortcutInfo addShortcut(Context context, Intent data,
int screen, int cellX, int cellY, boolean notify) {
ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,
int cellX, int cellY, boolean notify) {
final ShortcutInfo info = infoFromShortcutIntent(context, data, null);
addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
screen, cellX, cellY, notify);
addItemToDatabase(context, info, container, screen, cellX, cellY, notify);
return info;
}
+63 -27
View File
@@ -65,11 +65,11 @@ public class LauncherProvider extends ContentProvider {
private static final boolean LOGD = false;
private static final String DATABASE_NAME = "launcher.db";
private static final int DATABASE_VERSION = 8;
private static final int DATABASE_VERSION = 9;
static final String AUTHORITY = "com.android.launcher2.settings";
static final String TABLE_FAVORITES = "favorites";
static final String PARAMETER_NOTIFY = "notify";
@@ -199,7 +199,7 @@ public class LauncherProvider extends ContentProvider {
private static final String TAG_SEARCH = "search";
private static final String TAG_APPWIDGET = "appwidget";
private static final String TAG_SHORTCUT = "shortcut";
private final Context mContext;
private final AppWidgetHost mAppWidgetHost;
private long mMaxId = -1;
@@ -208,7 +208,12 @@ public class LauncherProvider extends ContentProvider {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
mMaxId = initializeMaxId(getWritableDatabase());
// In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
// the DB here
if (mMaxId == -1) {
mMaxId = initializeMaxId(getWritableDatabase());
}
}
/**
@@ -254,10 +259,10 @@ public class LauncherProvider extends ContentProvider {
mAppWidgetHost.deleteHost();
sendAppWidgetResetNotify();
}
if (!convertDatabase(db)) {
// Populate favorites table with initial favorites
loadFavorites(db);
loadFavorites(db, ItemInfo.NO_ID);
}
}
@@ -427,6 +432,18 @@ public class LauncherProvider extends ContentProvider {
version = 8;
}
if (version < 9) {
// The max id is not yet set at this point (onUpgrade is triggered in the ctor
// before it gets a change to get set, so we need to read it here when we use it)
if (mMaxId == -1) {
mMaxId = initializeMaxId(db);
}
// Add default hotseat icons
loadFavorites(db, LauncherSettings.Favorites.CONTAINER_HOTSEAT);
version = 9;
}
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -672,8 +689,9 @@ public class LauncherProvider extends ContentProvider {
* Loads the default set of favorite packages from an xml file.
*
* @param db The database to write the values into
* @param filterContainerId The specific container id of items to load
*/
private int loadFavorites(SQLiteDatabase db) {
private int loadFavorites(SQLiteDatabase db, long filterContainerId) {
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ContentValues values = new ContentValues();
@@ -700,26 +718,42 @@ public class LauncherProvider extends ContentProvider {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
values.clear();
values.put(LauncherSettings.Favorites.CONTAINER,
LauncherSettings.Favorites.CONTAINER_DESKTOP);
values.put(LauncherSettings.Favorites.SCREEN,
a.getString(R.styleable.Favorite_screen));
values.put(LauncherSettings.Favorites.CELLX,
a.getString(R.styleable.Favorite_x));
values.put(LauncherSettings.Favorites.CELLY,
a.getString(R.styleable.Favorite_y));
long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
if (a.hasValue(R.styleable.Favorite_container)) {
container = Long.valueOf(a.getString(R.styleable.Favorite_container));
}
if (filterContainerId == ItemInfo.NO_ID || filterContainerId == container) {
String screen = a.getString(R.styleable.Favorite_screen);
String x = a.getString(R.styleable.Favorite_x);
String y = a.getString(R.styleable.Favorite_y);
if (TAG_FAVORITE.equals(name)) {
added = addAppShortcut(db, values, a, packageManager, intent);
} else if (TAG_SEARCH.equals(name)) {
added = addSearchWidget(db, values);
} else if (TAG_CLOCK.equals(name)) {
added = addClockWidget(db, values);
} else if (TAG_APPWIDGET.equals(name)) {
added = addAppWidget(db, values, a, packageManager);
} else if (TAG_SHORTCUT.equals(name)) {
added = addUriShortcut(db, values, a);
// If we are adding to the hotset, the screen is used as the position in the
// hotset. This screen can't be at position 0 because AllApps is in the
// zeroth position.
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
Integer.valueOf(screen) <= 0) {
throw new RuntimeException("Invalid screen position for hotseat item");
}
values.clear();
values.put(LauncherSettings.Favorites.CONTAINER, container);
values.put(LauncherSettings.Favorites.SCREEN, screen);
values.put(LauncherSettings.Favorites.CELLX, x);
values.put(LauncherSettings.Favorites.CELLY, y);
System.out.println("Adding item to container: " + container);
if (TAG_FAVORITE.equals(name)) {
added = addAppShortcut(db, values, a, packageManager, intent);
} else if (TAG_SEARCH.equals(name)) {
added = addSearchWidget(db, values);
} else if (TAG_CLOCK.equals(name)) {
added = addClockWidget(db, values);
} else if (TAG_APPWIDGET.equals(name)) {
added = addAppWidget(db, values, a, packageManager);
} else if (TAG_SHORTCUT.equals(name)) {
added = addUriShortcut(db, values, a);
}
}
if (added) i++;
@@ -730,6 +764,8 @@ public class LauncherProvider extends ContentProvider {
Log.w(TAG, "Got exception parsing favorites.", e);
} catch (IOException e) {
Log.w(TAG, "Got exception parsing favorites.", e);
} catch (RuntimeException e) {
Log.w(TAG, "Got exception parsing favorites.", e);
}
return i;
@@ -133,6 +133,7 @@ class LauncherSettings {
* The icon is a resource identified by a package name and an integer id.
*/
static final int CONTAINER_DESKTOP = -100;
static final int CONTAINER_HOTSEAT = -101;
/**
* The screen holding the favorite (if container is CONTAINER_DESKTOP)
+189 -91
View File
@@ -424,12 +424,8 @@ public class Workspace extends SmoothPagedView
* @param spanX The number of cells spanned horizontally by the child.
* @param spanY The number of cells spanned vertically by the child.
*/
void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
addInScreen(child, screen, x, y, spanX, spanY, false);
}
void addInFullScreen(View child, int screen) {
addInScreen(child, screen, 0, 0, -1, -1);
void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY) {
addInScreen(child, container, screen, x, y, spanX, spanY, false);
}
/**
@@ -444,14 +440,32 @@ public class Workspace extends SmoothPagedView
* @param spanY The number of cells spanned vertically by the child.
* @param insert When true, the child is inserted at the beginning of the children list.
*/
void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
if (screen < 0 || screen >= getChildCount()) {
Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
+ " (was " + screen + "); skipping child");
return;
void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,
boolean insert) {
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (screen < 0 || screen >= getChildCount()) {
Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
+ " (was " + screen + "); skipping child");
return;
}
}
final CellLayout layout;
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
layout = mLauncher.getHotseat().getLayout();
if (screen < 0) {
screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
} else {
// Note: We do this to ensure that the hotseat is always laid out in the orientation
// of the hotseat in order regardless of which orientation they were added
x = mLauncher.getHotseat().getCellXFromOrder(screen);
y = mLauncher.getHotseat().getCellYFromOrder(screen);
}
} else {
layout = (CellLayout) getChildAt(screen);
}
final CellLayout group = (CellLayout) getChildAt(screen);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if (lp == null) {
lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
@@ -467,9 +481,9 @@ public class Workspace extends SmoothPagedView
}
// Get the canonical child id to uniquely represent this view in this screen
int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
boolean markCellsAsOccupied = !(child instanceof Folder);
if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
// TODO: This branch occurs when the workspace is adding views
// outside of the defined grid
// maybe we should be deleting these items from the LauncherModel?
@@ -1959,7 +1973,7 @@ public class Workspace extends SmoothPagedView
mDragInfo = cellInfo;
CellLayout current = (CellLayout) getChildAt(cellInfo.screen);
CellLayout current = getParentCellLayoutForView(cellInfo.cell);
current.onDragChild(child);
child.clearFocus();
@@ -2008,17 +2022,15 @@ public class Workspace extends SmoothPagedView
b.recycle();
}
void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
boolean insertAtFirst, int intersectX, int intersectY) {
final CellLayout cellLayout = (CellLayout) getChildAt(screen);
View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
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);
final int[] cellXY = new int[2];
cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
cellXY[0], cellXY[1]);
target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen, cellXY[0],
cellXY[1]);
}
/**
@@ -2051,7 +2063,6 @@ public class Workspace extends SmoothPagedView
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell);
if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell, true)) {
return true;
}
@@ -2074,8 +2085,12 @@ public class Workspace extends SmoothPagedView
boolean considerTimeout) {
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == targetCell[0] &&
mDragInfo.cellY == targetCell[1]) && mDragInfo.screen == indexOfChild(target);
boolean hasntMoved = false;
if (mDragInfo != null) {
CellLayout cellParent = getParentCellLayoutForView(mDragInfo.cell);
hasntMoved = (mDragInfo.cellX == targetCell[0] &&
mDragInfo.cellY == targetCell[1]) && (cellParent == target);
}
if (dropOverView == null || hasntMoved || (considerTimeout && !mCreateUserFolderOnDrop)) {
return false;
@@ -2100,7 +2115,7 @@ public class Workspace extends SmoothPagedView
return false;
}
boolean createUserFolderIfNecessary(View newView, CellLayout target,
boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
int[] targetCell, boolean external, DragView dragView, Runnable postAnimationRunnable) {
View v = target.getChildAt(targetCell[0], targetCell[1]);
boolean hasntMoved = mDragInfo != null
@@ -2118,16 +2133,15 @@ public class Workspace extends SmoothPagedView
ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
// if the drag started here, we need to remove it from the workspace
if (!external) {
int fromScreen = mDragInfo.screen;
CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
sourceLayout.removeView(newView);
getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
}
Rect folderLocation = new Rect();
float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
target.removeView(v);
FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]);
FolderIcon fi =
mLauncher.addFolder(target, container, screen, targetCell[0], targetCell[1]);
destInfo.cellX = -1;
destInfo.cellY = -1;
sourceInfo.cellX = -1;
@@ -2150,9 +2164,7 @@ public class Workspace extends SmoothPagedView
// if the drag started here, we need to remove it from the workspace
if (!external) {
int fromScreen = mDragInfo.screen;
CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
sourceLayout.removeView(newView);
getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
}
return true;
}
@@ -2166,7 +2178,11 @@ public class Workspace extends SmoothPagedView
// We want the point to be mapped to the dragTarget.
if (mDragTargetLayout != null) {
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
} else {
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
}
}
// When you are in customization mode and drag to a particular screen, make that the
@@ -2186,11 +2202,23 @@ public class Workspace extends SmoothPagedView
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
if (dropTargetLayout != null) {
// Move internally
final int screen = (mTargetCell[0] < 0) ?
mDragInfo.screen : indexOfChild(dropTargetLayout);
boolean continueDrop = true;
if (mLauncher.isHotseatLayout(mDragTargetLayout) && d.dragInfo instanceof ItemInfo) {
ItemInfo info = (ItemInfo) d.dragInfo;
if (info.spanX > 1 || info.spanY > 1) {
continueDrop = false;
Toast.makeText(getContext(), R.string.invalid_hotseat_item,
Toast.LENGTH_SHORT).show();
}
}
if (continueDrop && dropTargetLayout != null) {
// Move internally
long container = mLauncher.isHotseatLayout(dropTargetLayout) ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
int screen = (mTargetCell[0] < 0) ?
mDragInfo.screen : indexOfChild(dropTargetLayout);
int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
// First we find the cell nearest to point at which the item is
@@ -2199,10 +2227,10 @@ public class Workspace extends SmoothPagedView
mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
// If the item being dropped is a shortcut and the nearest drop
// cell also contains a shortcut, then create a folder with the two shortcuts.
boolean dropInscrollArea = mCurrentPage != screen;
boolean dropInscrollArea = mCurrentPage != screen && screen > -1;
if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout,
mTargetCell, false, d.dragView, null)) {
if (!dropInscrollArea && createUserFolderIfNecessary(cell, container,
dropTargetLayout, mTargetCell, false, d.dragView, null)) {
return;
}
@@ -2220,25 +2248,26 @@ public class Workspace extends SmoothPagedView
snapToPage(screen);
}
if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
if (screen != mDragInfo.screen) {
// Reparent the view
((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX,
mDragInfo.spanY);
getParentCellLayoutForView(cell).removeView(cell);
addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
mDragInfo.spanX, mDragInfo.spanY);
}
// update the item's position after drop
final ItemInfo info = (ItemInfo) cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
lp.cellX = mTargetCell[0];
lp.cellY = mTargetCell[1];
cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (cell instanceof LauncherAppWidgetHostView) {
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
cell instanceof LauncherAppWidgetHostView) {
final CellLayout cellLayout = dropTargetLayout;
// We post this call so that the widget has a chance to be placed
// in its final location
@@ -2264,9 +2293,8 @@ public class Workspace extends SmoothPagedView
}
}
LauncherModel.moveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
lp.cellX, lp.cellY);
LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
lp.cellY);
}
}
@@ -2446,7 +2474,8 @@ public class Workspace extends SmoothPagedView
final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
final PendingAddWidgetInfo createInfo =
new PendingAddWidgetInfo(widgetInfo, mimeType, data);
mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, null, pos);
mLauncher.addAppWidgetFromDrop(createInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, null, pos);
} else {
// Show the widget picker dialog if there is more than one widget
// that can handle this data type
@@ -2506,6 +2535,15 @@ public class Workspace extends SmoothPagedView
cachedInverseMatrix.mapPoints(xy);
}
/*
* Maps a point from the Workspace's coordinate system to another sibling view's. (Workspace
* covers the full screen)
*/
void mapPointFromSelfToSibling(View v, float[] xy) {
xy[0] = xy[0] - v.getLeft();
xy[1] = xy[1] - v.getTop();
}
/*
*
* Convert the 2D coordinate xy from this CellLayout's coordinate space to
@@ -2581,7 +2619,7 @@ public class Workspace extends SmoothPagedView
float smallestDistSoFar = Float.MAX_VALUE;
for (int i = 0; i < screenCount; i++) {
CellLayout cl = (CellLayout)getChildAt(i);
CellLayout cl = (CellLayout) getChildAt(i);
final float[] touchXy = mTempTouchCoordinates;
touchXy[0] = originX + offsetX;
@@ -2657,7 +2695,7 @@ public class Workspace extends SmoothPagedView
if (mInScrollArea) return;
if (mIsSwitchingState) return;
CellLayout layout;
CellLayout layout = null;
ItemInfo item = (ItemInfo) d.dragInfo;
// Ensure that we have proper spans for the item that we are dropping
@@ -2690,7 +2728,17 @@ public class Workspace extends SmoothPagedView
}
}
} else {
layout = getCurrentDropLayout();
// Test to see if we are over the hotseat otherwise just use the current page
Rect r = new Rect();
if (mLauncher.getHotseat() != null) {
mLauncher.getHotseat().getHitRect(r);
if (r.contains(d.x, d.y)) {
layout = mLauncher.getHotseat().getLayout();
}
}
if (layout == null) {
layout = getCurrentDropLayout();
}
if (layout != mDragTargetLayout) {
if (mDragTargetLayout != null) {
mDragTargetLayout.setIsDragOverlapping(false);
@@ -2710,7 +2758,11 @@ public class Workspace extends SmoothPagedView
d.dragView, mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
} else {
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
}
ItemInfo info = (ItemInfo) d.dragInfo;
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
@@ -2845,8 +2897,12 @@ public class Workspace extends SmoothPagedView
spanY = mDragInfo.spanY;
}
final long container = mLauncher.isHotseatLayout(cellLayout) ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
final int screen = indexOfChild(cellLayout);
if (screen != mCurrentPage && mState != State.SPRING_LOADED) {
if (!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
&& mState != State.SPRING_LOADED) {
snapToPage(screen);
}
@@ -2863,11 +2919,11 @@ public class Workspace extends SmoothPagedView
switch (pendingInfo.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
screen, mTargetCell, null);
container, screen, mTargetCell, null);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(pendingInfo.componentName,
screen, mTargetCell, null);
container, screen, mTargetCell, null);
break;
default:
throw new IllegalStateException("Unknown item type: " +
@@ -2923,8 +2979,8 @@ public class Workspace extends SmoothPagedView
mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
cellLayout, mTargetCell);
d.postAnimationRunnable = exitSpringLoadedRunnable;
if (createUserFolderIfNecessary(view, cellLayout, mTargetCell, true, d.dragView,
d.postAnimationRunnable)) {
if (createUserFolderIfNecessary(view, container, cellLayout, mTargetCell, true,
d.dragView, d.postAnimationRunnable)) {
return;
}
if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, d, true)) {
@@ -2939,15 +2995,14 @@ public class Workspace extends SmoothPagedView
} else {
cellLayout.findCellForSpan(mTargetCell, 1, 1);
}
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
addInScreen(view, container, screen, mTargetCell[0], mTargetCell[1], info.spanX,
info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
cellLayout.animateDrop();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
cellLayout.getChildrenLayout().measureChild(view);
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen,
lp.cellX, lp.cellY);
if (d.dragView != null) {
@@ -3016,8 +3071,7 @@ public class Workspace extends SmoothPagedView
if (success) {
if (target != this) {
if (mDragInfo != null) {
final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
cellLayout.removeView(mDragInfo.cell);
getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
if (mDragInfo.cell instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
}
@@ -3028,7 +3082,13 @@ public class Workspace extends SmoothPagedView
// calling onDropCompleted(). We call it ourselves here, but maybe this should be
// moved into DragController.cancelDrag().
doDragExit(null);
((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
CellLayout cellLayout;
if (mLauncher.isHotseatLayout(target)) {
cellLayout = mLauncher.getHotseat().getLayout();
} else {
cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
}
cellLayout.onDropChild(mDragInfo.cell);
}
mDragOutline = null;
mDragInfo = null;
@@ -3125,15 +3185,58 @@ public class Workspace extends SmoothPagedView
mInScrollArea = false;
}
public Folder getFolderForTag(Object tag) {
final int screenCount = getChildCount();
/**
* Returns a specific CellLayout
*/
CellLayout getParentCellLayoutForView(View v) {
ArrayList<CellLayout> layouts = getWorkspaceAndHotseatCellLayouts();
for (CellLayout layout : layouts) {
if (layout.getChildrenLayout().indexOfChild(v) > -1) {
return layout;
}
}
return null;
}
/**
* Returns a list of all the CellLayouts in the workspace.
*/
ArrayList<CellLayout> getWorkspaceAndHotseatCellLayouts() {
ArrayList<CellLayout> layouts = new ArrayList<CellLayout>();
int screenCount = getChildCount();
for (int screen = 0; screen < screenCount; screen++) {
ViewGroup currentScreen = ((CellLayout) getChildAt(screen)).getChildrenLayout();
int count = currentScreen.getChildCount();
layouts.add(((CellLayout) getChildAt(screen)));
}
if (mLauncher.getHotseat() != null) {
layouts.add(mLauncher.getHotseat().getLayout());
}
return layouts;
}
/**
* We should only use this to search for specific children. Do not use this method to modify
* CellLayoutChildren directly.
*/
ArrayList<CellLayoutChildren> getWorkspaceAndHotseatCellLayoutChildren() {
ArrayList<CellLayoutChildren> childrenLayouts = new ArrayList<CellLayoutChildren>();
int screenCount = getChildCount();
for (int screen = 0; screen < screenCount; screen++) {
childrenLayouts.add(((CellLayout) getChildAt(screen)).getChildrenLayout());
}
if (mLauncher.getHotseat() != null) {
childrenLayouts.add(mLauncher.getHotseat().getLayout().getChildrenLayout());
}
return childrenLayouts;
}
public Folder getFolderForTag(Object tag) {
ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
for (CellLayoutChildren layout: childrenLayouts) {
int count = layout.getChildCount();
for (int i = 0; i < count; i++) {
View child = currentScreen.getChildAt(i);
View child = layout.getChildAt(i);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
if (child instanceof Folder) {
Folder f = (Folder) child;
if (f.getInfo() == tag && f.getInfo().opened) {
return f;
@@ -3145,12 +3248,11 @@ public class Workspace extends SmoothPagedView
}
public View getViewForTag(Object tag) {
int screenCount = getChildCount();
for (int screen = 0; screen < screenCount; screen++) {
ViewGroup currentScreen = ((CellLayout) getChildAt(screen)).getChildrenLayout();
int count = currentScreen.getChildCount();
ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
for (CellLayoutChildren layout: childrenLayouts) {
int count = layout.getChildCount();
for (int i = 0; i < count; i++) {
View child = currentScreen.getChildAt(i);
View child = layout.getChildAt(i);
if (child.getTag() == tag) {
return child;
}
@@ -3160,11 +3262,8 @@ public class Workspace extends SmoothPagedView
}
void clearDropTargets() {
final int screenCount = getChildCount();
for (int i = 0; i < screenCount; i++) {
final CellLayout layoutParent = (CellLayout) getChildAt(i);
final ViewGroup layout = layoutParent.getChildrenLayout();
ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
for (CellLayoutChildren layout: childrenLayouts) {
int childCount = layout.getChildCount();
for (int j = 0; j < childCount; j++) {
View v = layout.getChildAt(j);
@@ -3185,8 +3284,8 @@ public class Workspace extends SmoothPagedView
packageNames.add(apps.get(i).componentName.getPackageName());
}
for (int i = 0; i < screenCount; i++) {
final CellLayout layoutParent = (CellLayout) getChildAt(i);
ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
for (final CellLayout layoutParent: cellLayouts) {
final ViewGroup layout = layoutParent.getChildrenLayout();
// Avoid ANRs by treating each screen separately
@@ -3273,9 +3372,8 @@ public class Workspace extends SmoothPagedView
}
void updateShortcuts(ArrayList<ApplicationInfo> apps) {
final int screenCount = getChildCount();
for (int i = 0; i < screenCount; i++) {
final ViewGroup layout = ((CellLayout) getChildAt(i)).getChildrenLayout();
ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
for (CellLayoutChildren layout: childrenLayouts) {
int childCount = layout.getChildCount();
for (int j = 0; j < childCount; j++) {
final View view = layout.getChildAt(j);
@@ -3307,7 +3405,7 @@ public class Workspace extends SmoothPagedView
void moveToDefaultScreen(boolean animate) {
if (isSmall() || mIsSwitchingState) {
mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
mLauncher.showWorkspace(animate, (CellLayout) getChildAt(mDefaultPage));
} else if (animate) {
snapToPage(mDefaultPage);
} else {