summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml92
-rw-r--r--res/drawable/google_logo.pngbin5953 -> 3361 bytes
-rw-r--r--res/layout-land/application_boxed.xml8
-rw-r--r--res/layout-land/launcher.xml28
-rw-r--r--res/layout-land/live_folder_grid.xml49
-rw-r--r--res/layout-land/live_folder_icon.xml21
-rw-r--r--res/layout-port/application_boxed.xml8
-rw-r--r--res/layout-port/launcher.xml28
-rw-r--r--res/layout-port/live_folder_grid.xml49
-rw-r--r--res/layout-port/live_folder_icon.xml21
-rw-r--r--res/layout/application_list.xml70
-rw-r--r--res/layout/live_folder_list.xml42
-rw-r--r--res/layout/widget_search.xml12
-rw-r--r--res/values-de/strings.xml46
-rw-r--r--res/values-ja/strings.xml46
-rw-r--r--res/values/attrs.xml24
-rw-r--r--res/values/strings.xml45
-rw-r--r--res/values/styles.xml2
-rw-r--r--src/com/android/launcher/AddAdapter.java67
-rw-r--r--src/com/android/launcher/ApplicationInfo.java24
-rw-r--r--src/com/android/launcher/BubbleTextView.java55
-rw-r--r--src/com/android/launcher/CellLayout.java11
-rw-r--r--src/com/android/launcher/DeleteZone.java14
-rw-r--r--src/com/android/launcher/FastBitmapDrawable.java73
-rw-r--r--src/com/android/launcher/Folder.java19
-rw-r--r--src/com/android/launcher/FolderIcon.java5
-rw-r--r--src/com/android/launcher/FolderInfo.java5
-rw-r--r--src/com/android/launcher/HandleView.java91
-rw-r--r--src/com/android/launcher/InstallShortcutReceiver.java28
-rw-r--r--src/com/android/launcher/ItemInfo.java32
-rw-r--r--src/com/android/launcher/Launcher.java311
-rw-r--r--src/com/android/launcher/LauncherApplication.java29
-rw-r--r--src/com/android/launcher/LauncherModel.java352
-rw-r--r--src/com/android/launcher/LauncherProvider.java435
-rw-r--r--src/com/android/launcher/LauncherSettings.java222
-rw-r--r--src/com/android/launcher/LiveFolder.java83
-rw-r--r--src/com/android/launcher/LiveFolderAdapter.java205
-rw-r--r--src/com/android/launcher/LiveFolderIcon.java76
-rw-r--r--src/com/android/launcher/LiveFolderInfo.java75
-rw-r--r--src/com/android/launcher/Search.java36
-rw-r--r--src/com/android/launcher/UninstallShortcutReceiver.java20
-rw-r--r--src/com/android/launcher/UserFolder.java19
-rw-r--r--src/com/android/launcher/UserFolderInfo.java10
-rw-r--r--src/com/android/launcher/Utilities.java63
-rw-r--r--src/com/android/launcher/WallpaperChooser.java1
-rw-r--r--src/com/android/launcher/Widget.java7
-rw-r--r--src/com/android/launcher/Workspace.java17
47 files changed, 2522 insertions, 454 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 812985191..966848321 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,41 +17,59 @@
** limitations under the License.
*/
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.launcher"
- android:sharedUserId="android.uid.shared">
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher"
+ android:sharedUserId="android.uid.shared">
- <permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="normal"
- android:label="@string/permlab_install_shortcut"
- android:description="@string/permdesc_install_shortcut"/>
- <permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="normal"
- android:label="@string/permlab_uninstall_shortcut"
- android:description="@string/permdesc_uninstall_shortcut"/>
+ <permission
+ android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_install_shortcut"
+ android:description="@string/permdesc_install_shortcut" />
+ <permission
+ android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_uninstall_shortcut"
+ android:description="@string/permdesc_uninstall_shortcut"/>
+ <permission
+ android:name="com.android.launcher.permission.READ_SETTINGS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_read_settings"
+ android:description="@string/permdesc_read_settings"/>
+ <permission
+ android:name="com.android.launcher.permission.WRITE_SETTINGS"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_write_settings"
+ android:description="@string/permdesc_write_settings"/>
- <uses-permission android:name="android.permission.CALL_PHONE"/>
- <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
- <uses-permission android:name="android.permission.GET_TASKS"/>
+ <uses-permission android:name="android.permission.CALL_PHONE" />
+ <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
+ <uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
- <uses-permission android:name="android.permission.VIBRATE"/>
- <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
+ <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<application
+ android:name="LauncherApplication"
android:process="android.process.acore"
android:label="@string/application_name"
android:icon="@drawable/ic_launcher_home">
- <activity android:name="Launcher"
- android:launchMode="singleTask"
- android:clearTaskOnLaunch="true"
- android:stateNotNeeded="true"
- android:theme="@style/Theme"
- android:configChanges="mcc|mnc">
+ <activity
+ android:name="Launcher"
+ android:launchMode="singleTask"
+ android:clearTaskOnLaunch="true"
+ android:stateNotNeeded="true"
+ android:theme="@style/Theme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
@@ -60,7 +78,8 @@
</intent-filter>
</activity>
- <activity android:name="WallpaperChooser"
+ <activity
+ android:name="WallpaperChooser"
android:label="@string/pick_wallpaper"
android:icon="@drawable/ic_launcher_gallery">
<intent-filter>
@@ -70,21 +89,34 @@
</activity>
<!-- Enable system-default search mode for any activity in Home -->
- <meta-data android:name="android.app.default_searchable" android:value="*" />
+ <meta-data
+ android:name="android.app.default_searchable"
+ android:value="*" />
- <receiver android:name=".InstallShortcutReceiver"
- android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
+ <!-- Intent received used to install shortcuts from other applications -->
+ <receiver
+ android:name=".InstallShortcutReceiver"
+ android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
<intent-filter>
<action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
</intent-filter>
</receiver>
- <receiver android:name=".UninstallShortcutReceiver"
- android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
+ <!-- Intent received used to uninstall shortcuts from other applications -->
+ <receiver
+ android:name=".UninstallShortcutReceiver"
+ android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
<intent-filter>
<action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
</intent-filter>
</receiver>
+ <!-- The settings provider contains Home's data, like the workspace favorites -->
+ <provider
+ android:name="LauncherProvider"
+ android:authorities="com.android.launcher.settings"
+ android:writePermission="com.android.launcher.permission.WRITE_SETTINGS"
+ android:readPermission="com.android.launcher.permission.READ_SETTINGS" />
+
</application>
</manifest>
diff --git a/res/drawable/google_logo.png b/res/drawable/google_logo.png
index 738abe013..54fd5f961 100644
--- a/res/drawable/google_logo.png
+++ b/res/drawable/google_logo.png
Binary files differ
diff --git a/res/layout-land/application_boxed.xml b/res/layout-land/application_boxed.xml
index 3cec8d0be..63d2254b4 100644
--- a/res/layout-land/application_boxed.xml
+++ b/res/layout-land/application_boxed.xml
@@ -15,15 +15,17 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="88dip"
- android:paddingTop="6dip"
- android:paddingBottom="3dip"
+ android:paddingTop="5dip"
+ android:paddingBottom="2dip"
android:drawablePadding="0dip"
android:textSize="13dip"
android:maxLines="2"
- android:ellipsize="end"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
android:textColor="@color/bright_text_dark_focused"
android:gravity="top|center_horizontal" />
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index e93ef31d2..11a81fd8e 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -16,6 +16,7 @@
<com.android.launcher.DragLayer
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:id="@+id/drag_layer"
@@ -30,9 +31,9 @@
launcher:defaultScreen="1">
- <include layout="@layout/workspace_screen" />
- <include layout="@layout/workspace_screen" />
- <include layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
</com.android.launcher.Workspace>
@@ -42,19 +43,24 @@
android:layout_height="fill_parent"
android:orientation="horizontal"
- android:bottomOffset="7px"
- android:handle="@+id/all_apps"
- android:content="@+id/content">
-
- <ImageView
+ androidprv:bottomOffset="7px"
+ androidprv:handle="@+id/all_apps"
+ androidprv:content="@+id/content">
+
+ <com.android.launcher.HandleView
android:id="@id/all_apps"
+ android:layout_width="56dip"
+ android:layout_height="fill_parent"
+
+ android:background="@drawable/handle"
+
android:focusable="true"
android:clickable="true"
+
android:scaleType="center"
android:src="@drawable/handle_icon"
- android:background="@drawable/handle"
- android:layout_height="fill_parent"
- android:layout_width="56dip" />
+
+ launcher:direction="vertical" />
<com.android.launcher.AllAppsGridView
android:id="@id/content"
diff --git a/res/layout-land/live_folder_grid.xml b/res/layout-land/live_folder_grid.xml
new file mode 100644
index 000000000..d1b02a4a6
--- /dev/null
+++ b/res/layout-land/live_folder_grid.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<com.android.launcher.LiveFolder xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/close"
+ android:background="@drawable/box_launcher_top"
+ android:gravity="left|center_vertical"
+ android:textSize="14sp"
+ android:textColor="#404040"
+ android:textStyle="bold"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ <GridView
+ android:id="@id/content"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:background="@drawable/box_launcher_bottom"
+
+ android:scrollbarAlwaysDrawVerticalTrack="true"
+ android:scrollbarStyle="insideInset"
+ android:drawSelectorOnTop="false"
+ android:listSelector="@drawable/grid_selector"
+
+ android:verticalSpacing="10dip"
+ android:numColumns="5" />
+
+</com.android.launcher.LiveFolder>
diff --git a/res/layout-land/live_folder_icon.xml b/res/layout-land/live_folder_icon.xml
new file mode 100644
index 000000000..7b6d58dad
--- /dev/null
+++ b/res/layout-land/live_folder_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<com.android.launcher.LiveFolderIcon xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/WorkspaceIcon.Landscape" />
diff --git a/res/layout-port/application_boxed.xml b/res/layout-port/application_boxed.xml
index 3cec8d0be..63d2254b4 100644
--- a/res/layout-port/application_boxed.xml
+++ b/res/layout-port/application_boxed.xml
@@ -15,15 +15,17 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="88dip"
- android:paddingTop="6dip"
- android:paddingBottom="3dip"
+ android:paddingTop="5dip"
+ android:paddingBottom="2dip"
android:drawablePadding="0dip"
android:textSize="13dip"
android:maxLines="2"
- android:ellipsize="end"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
android:textColor="@color/bright_text_dark_focused"
android:gravity="top|center_horizontal" />
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 41a1f5b0d..167331e86 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -16,6 +16,7 @@
<com.android.launcher.DragLayer
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:id="@+id/drag_layer"
@@ -30,9 +31,9 @@
launcher:defaultScreen="1">
- <include layout="@layout/workspace_screen" />
- <include layout="@layout/workspace_screen" />
- <include layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
</com.android.launcher.Workspace>
@@ -41,20 +42,25 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:topOffset="5px"
- android:bottomOffset="7px"
- android:handle="@+id/all_apps"
- android:content="@+id/content">
+ androidprv:topOffset="5px"
+ androidprv:bottomOffset="7px"
+ androidprv:handle="@+id/all_apps"
+ androidprv:content="@+id/content">
- <ImageView
+ <com.android.launcher.HandleView
android:id="@id/all_apps"
+ android:layout_width="fill_parent"
+ android:layout_height="56dip"
+
+ android:background="@drawable/handle"
+
android:focusable="true"
android:clickable="true"
+
android:scaleType="center"
android:src="@drawable/handle_icon"
- android:background="@drawable/handle"
- android:layout_width="fill_parent"
- android:layout_height="56dip" />
+
+ launcher:direction="horizontal" />
<com.android.launcher.AllAppsGridView
android:id="@id/content"
diff --git a/res/layout-port/live_folder_grid.xml b/res/layout-port/live_folder_grid.xml
new file mode 100644
index 000000000..ec32d417c
--- /dev/null
+++ b/res/layout-port/live_folder_grid.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<com.android.launcher.LiveFolder xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/close"
+ android:background="@drawable/box_launcher_top"
+ android:gravity="left|center_vertical"
+ android:textSize="14sp"
+ android:textColor="#404040"
+ android:textStyle="bold"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ <GridView
+ android:id="@id/content"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:background="@drawable/box_launcher_bottom"
+
+ android:scrollbarAlwaysDrawVerticalTrack="true"
+ android:scrollbarStyle="insideInset"
+ android:drawSelectorOnTop="false"
+ android:listSelector="@drawable/grid_selector"
+
+ android:verticalSpacing="10dip"
+ android:numColumns="4" />
+
+</com.android.launcher.LiveFolder>
diff --git a/res/layout-port/live_folder_icon.xml b/res/layout-port/live_folder_icon.xml
new file mode 100644
index 000000000..dc711f3cf
--- /dev/null
+++ b/res/layout-port/live_folder_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<com.android.launcher.LiveFolderIcon xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/WorkspaceIcon.Portrait" />
diff --git a/res/layout/application_list.xml b/res/layout/application_list.xml
new file mode 100644
index 000000000..230a95197
--- /dev/null
+++ b/res/layout/application_list.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+
+ android:paddingLeft="10dip"
+
+ android:orientation="horizontal">
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dip"
+ android:layout_weight="1.0"
+ android:layout_height="fill_parent"
+
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+
+ android:orientation="vertical"
+ android:gravity="center_vertical">
+
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+
+ android:singleLine="true"
+ android:ellipsize="end"
+
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView android:id="@+id/description"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+
+ android:layout_below="@id/name"
+ android:layout_alignLeft="@id/name"
+
+ android:singleLine="true"
+ android:ellipsize="end"
+
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/live_folder_list.xml b/res/layout/live_folder_list.xml
new file mode 100644
index 000000000..1d32f8878
--- /dev/null
+++ b/res/layout/live_folder_list.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<com.android.launcher.LiveFolder xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/close"
+ android:background="@drawable/box_launcher_top"
+ android:gravity="left|center_vertical"
+ android:textSize="14sp"
+ android:textColor="#404040"
+ android:textStyle="bold"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ <ListView
+ android:id="@id/content"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:cacheColorHint="#00000000"
+ android:background="@drawable/box_launcher_bottom" />
+
+</com.android.launcher.LiveFolder>
diff --git a/res/layout/widget_search.xml b/res/layout/widget_search.xml
index 67ac34582..4343e2792 100644
--- a/res/layout/widget_search.xml
+++ b/res/layout/widget_search.xml
@@ -34,15 +34,15 @@
android:hint="@string/search_hint"
android:focusableInTouchMode="false"
android:singleLine="true"
-
+ android:selectAllOnFocus="true"
android:completionThreshold="1"
/>
- <Button
- android:id="@+id/go"
- android:layout_marginLeft="4dip"
+ <ImageButton android:id="@+id/search_go_btn"
+ android:layout_marginLeft="1dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/go"/>
-
+ android:src="@android:drawable/ic_btn_search"
+ />
+
</com.android.launcher.Search>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 000000000..7d3af0791
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="application_name">"Startseite"</string>
+ <string name="folder_name">"Ordner"</string>
+ <string name="chooser_wallpaper">"Hintergrund auswählen"</string>
+ <string name="wallpaper_instructions">"Hintergrund festlegen"</string>
+ <string name="pick_wallpaper">"Galerie"</string>
+ <string name="activity_not_found">"Anwendung ist nicht auf dem Telefon installiert."</string>
+ <!-- no translation found for rename_folder_label (5646236631298452787) -->
+ <skip />
+ <string name="rename_folder_title">"Ordner umbenennen"</string>
+ <string name="rename_action">"OK"</string>
+ <string name="cancel_action">"Abbrechen"</string>
+ <!-- no translation found for menu_item_add_item (6233177331075781114) -->
+ <skip />
+ <string name="group_applications">"Anwendung"</string>
+ <string name="group_shortcuts">"Verknüpfung"</string>
+ <!-- no translation found for group_live_folders (3057578584715591220) -->
+ <skip />
+ <string name="group_widgets">"Widget"</string>
+ <string name="group_wallpapers">"Hintergrund"</string>
+ <string name="add_folder">"Ordner"</string>
+ <string name="add_clock">"Uhr"</string>
+ <string name="add_photo_frame">"Bildrahmen"</string>
+ <string name="add_search">"Suchen"</string>
+ <string name="out_of_space">"Auf der Startseite ist kein Platz mehr vorhanden."</string>
+ <string name="menu_add">"Hinzufügen"</string>
+ <string name="menu_wallpaper">"Hintergrund"</string>
+ <string name="menu_search">"Suchen"</string>
+ <string name="menu_notifications">"Benachrichtigungen"</string>
+ <string name="menu_settings">"Einstellungen"</string>
+ <string name="permlab_install_shortcut">"Verknüpfungen installieren"</string>
+ <string name="permdesc_install_shortcut">"Ermöglicht einer Anwendung das Hinzufügen von Verknüpfungen ohne Eingriff des Benutzers."</string>
+ <string name="permlab_uninstall_shortcut">"Verknüpfungen deinstallieren"</string>
+ <string name="permdesc_uninstall_shortcut">"Ermöglicht einer Anwendung das Entfernen von Verknüpfungen ohne Eingriff des Benutzers."</string>
+ <!-- no translation found for permlab_read_settings (3452408290738106747) -->
+ <skip />
+ <!-- no translation found for permdesc_read_settings (8377434937176025492) -->
+ <skip />
+ <!-- no translation found for permlab_write_settings (1360567537236705628) -->
+ <skip />
+ <!-- no translation found for permdesc_write_settings (1098648778383349818) -->
+ <skip />
+ <string name="search_hint">"Google-Suche"</string>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 000000000..11d24bc38
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="application_name">"ホーム"</string>
+ <string name="folder_name">"フォルダ"</string>
+ <string name="chooser_wallpaper">"壁紙を選択"</string>
+ <string name="wallpaper_instructions">"壁紙に設定"</string>
+ <string name="pick_wallpaper">"壁紙ギャラリー"</string>
+ <string name="activity_not_found">"アプリケーションがインストールされていません。"</string>
+ <!-- no translation found for rename_folder_label (5646236631298452787) -->
+ <skip />
+ <string name="rename_folder_title">"フォルダ名を変更"</string>
+ <string name="rename_action">"OK"</string>
+ <string name="cancel_action">"キャンセル"</string>
+ <!-- no translation found for menu_item_add_item (6233177331075781114) -->
+ <skip />
+ <string name="group_applications">"アプリケーション"</string>
+ <string name="group_shortcuts">"ショートカット"</string>
+ <!-- no translation found for group_live_folders (3057578584715591220) -->
+ <skip />
+ <string name="group_widgets">"ウィジェット"</string>
+ <string name="group_wallpapers">"壁紙"</string>
+ <string name="add_folder">"フォルダ"</string>
+ <string name="add_clock">"時計"</string>
+ <string name="add_photo_frame">"写真フレーム"</string>
+ <string name="add_search">"検索"</string>
+ <string name="out_of_space">"このホーム画面には空きスペースがありません。"</string>
+ <string name="menu_add">"追加"</string>
+ <string name="menu_wallpaper">"壁紙"</string>
+ <string name="menu_search">"検索"</string>
+ <string name="menu_notifications">"通知"</string>
+ <string name="menu_settings">"設定"</string>
+ <string name="permlab_install_shortcut">"ショートカットのインストール"</string>
+ <string name="permdesc_install_shortcut">"ユーザー操作なしで、ショートカットをアプリケーションで追加できるようにします。"</string>
+ <string name="permlab_uninstall_shortcut">"ショートカットのアンインストール"</string>
+ <string name="permdesc_uninstall_shortcut">"ユーザー操作なしで、ショートカットをアプリケーションで削除できるようにします。"</string>
+ <!-- no translation found for permlab_read_settings (3452408290738106747) -->
+ <skip />
+ <!-- no translation found for permdesc_read_settings (8377434937176025492) -->
+ <skip />
+ <!-- no translation found for permlab_write_settings (1360567537236705628) -->
+ <skip />
+ <!-- no translation found for permdesc_write_settings (1098648778383349818) -->
+ <skip />
+ <string name="search_hint">"Google検索"</string>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index caa243849..87f5b788b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -17,6 +17,16 @@
-->
<resources>
+ <!-- Orientation of a widget. -->
+ <attr name="direction">
+ <!-- Vertical widget. -->
+ <enum name="vertical" value="0" />
+ <!-- Horizontal widget. -->
+ <enum name="horizontal" value="1" />
+ </attr>
+
+ <skip />
+
<!-- Workspace specific attributes. These attributes are used to customize
the workspace in XML files. -->
<declare-styleable name="Workspace">
@@ -49,12 +59,14 @@
a DeleteZone view in XML files. -->
<declare-styleable name="DeleteZone">
<!-- Orientation of the delete zone. -->
- <attr name="direction">
- <!-- Vertical delete zone. -->
- <enum name="vertical" value="0" />
- <!-- Horizontal delete zone. This is the default value. -->
- <enum name="horizontal" value="1" />
- </attr>
+ <attr name="direction" />
+ </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>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d2a997a1e..c1d3455ae 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -19,52 +19,66 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- General -->
+ <skip />
<!-- Application name -->
<string name="application_name">Home</string>
<!-- Default folder name -->
<string name="folder_name">Folder</string>
- <!-- Unused string -->
- <string name="all_apps_folder_name">Applications</string>
- <!-- Unused string -->
- <string name="delete_name">Delete</string>
<!-- Title of dialog that appears after user selects Wallpaper from menu -->
<string name="chooser_wallpaper">Select wallpaper from</string>
<!-- Button label on Wallpaper Gallery screen; user selects this button to set a specific wallpaper -->
<string name="wallpaper_instructions">Set wallpaper</string>
<!-- Option in "Select wallpaper from" dialog box -->
<string name="pick_wallpaper">Wallpaper gallery</string>
- <!--Displayed when user selects a shortcut for an app that was uninstalled -->
+ <!-- Displayed when user selects a shortcut for an app that was uninstalled -->
<string name="activity_not_found">Application is not installed on your phone.</string>
<!-- Folders -->
+ <skip />
<!-- Label of Folder name field in Rename folder dialog box -->
- <string name="rename_folder_label">Folder name:</string>
+ <string name="rename_folder_label">Folder name</string>
<!-- Title of dialog box -->
<string name="rename_folder_title">Rename folder</string>
- <!-- Buttons in Rename folder dialog box: -->
+ <!-- Buttons in Rename folder dialog box -->
<string name="rename_action">OK</string>
+ <!-- Buttons in Rename folder dialog box -->
<string name="cancel_action">Cancel</string>
<!-- Shortcuts -->
+ <skip />
<!-- Title of dialog box -->
- <string name="menu_item_add_item">Add to Home</string>
- <!-- Options in "Add to Home" dialog box: -->
+ <string name="menu_item_add_item">Add to Home screen</string>
+ <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all apps -->
<string name="group_applications">Application</string>
+ <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all shortcuts -->
<string name="group_shortcuts">Shortcut</string>
+ <string name="group_live_folders">Live folder</string>
+ <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all widgets -->
<string name="group_widgets">Widget</string>
+ <!-- Options in "Add to Home" dialog box; Title of the group containing the list of apps that can set the wallpaper-->
<string name="group_wallpapers">Wallpaper</string>
+ <!-- Options in "Add to Home" dialog box; Name of the Folder widget-->
<string name="add_folder">Folder</string>
+ <!-- Options in "Add to Home" dialog box; Name of the Clock widget-->
<string name="add_clock">Clock</string>
+ <!-- Options in "Add to Home" dialog box; Name of the Picture frame widget-->
<string name="add_photo_frame">Picture frame</string>
+ <!-- Options in "Add to Home" dialog box; Name of the Google Search widget-->
<string name="add_search">Search</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>
<!-- Menus items: -->
+ <skip />
+ <!-- Verb, menu item used to add an item on the desktop -->
<string name="menu_add">Add</string>
+ <!-- Noun, menu item used to set the desktop's wallpaper -->
<string name="menu_wallpaper">Wallpaper</string>
+ <!-- Verb, menu item used to initiate a Google Search -->
<string name="menu_search">Search</string>
+ <!-- Noun, menu item used to bring down the notifications shade -->
<string name="menu_notifications">Notifications</string>
+ <!-- Noun, menu item used to show the system settings -->
<string name="menu_settings">Settings</string>
<!-- Permissions: -->
@@ -74,9 +88,18 @@
<string name="permlab_uninstall_shortcut">uninstall shortcuts</string>
<string name="permdesc_uninstall_shortcut">Allows an application to remove
shortcuts without user intervention.</string>
-
+ <string name="permlab_read_settings">read Home settings and shortcuts</string>
+ <string name="permdesc_read_settings">Allows an application to read the settings and
+ shortcuts in Home.</string>
+ <string name="permlab_write_settings">write Home settings and shortcuts</string>
+ <string name="permdesc_write_settings">Allows an application to change the settings and
+ shortcuts in Home.</string>
+
<!-- Widgets: -->
- <string name="go">Search</string>
+ <skip />
+ <!-- This is the hint text shown in the search widget, before text is entered.
+ This translation SHOULD MATCH the string "search_hint" which is found in
+ GoogleSearch/res/values/strings.xml -->
<string name="search_hint">Google Search</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a5aed0169..a3d3e22c7 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -26,7 +26,7 @@
<style name="WorkspaceIcon">
<item name="android:textSize">13dip</item>
<item name="android:singleLine">true</item>
- <item name="android:ellipsize">end</item>
+ <item name="android:ellipsize">marquee</item>
<item name="android:shadowColor">#FF000000</item>
<item name="android:shadowRadius">2.0</item>
<item name="android:textColor">#FFF</item>
diff --git a/src/com/android/launcher/AddAdapter.java b/src/com/android/launcher/AddAdapter.java
index 49422c671..8eebe39d9 100644
--- a/src/com/android/launcher/AddAdapter.java
+++ b/src/com/android/launcher/AddAdapter.java
@@ -28,6 +28,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.BaseExpandableListAdapter;
import android.graphics.drawable.Drawable;
+import android.provider.LiveFolders;
import java.util.ArrayList;
import java.util.Collections;
@@ -40,9 +41,11 @@ public final class AddAdapter extends BaseExpandableListAdapter {
private static final int GROUP_APPLICATIONS = 0;
private static final int GROUP_SHORTCUTS = 1;
private static final int GROUP_WIDGETS = 2;
- private static final int GROUP_WALLPAPERS = 3;
+ private static final int GROUP_LIVE_FOLDERS = 3;
+ private static final int GROUP_WALLPAPERS = 4;
private final Intent mCreateShortcutIntent;
+ private final Intent mCreateLiveFolderIntent;
private Intent mSetWallpaperIntent;
private final LayoutInflater mInflater;
private Launcher mLauncher;
@@ -52,7 +55,7 @@ public final class AddAdapter extends BaseExpandableListAdapter {
* Abstract class representing one thing that can be added
*/
public abstract class AddAction implements Runnable {
- private final Context mContext;
+ protected final Context mContext;
AddAction(Context context) {
mContext = context;
@@ -110,8 +113,9 @@ public final class AddAdapter extends BaseExpandableListAdapter {
mLabel = info.activityInfo.name;
}
}
+
if (mIcon == null) {
- mIcon = info.loadIcon(pm);
+ mIcon = Utilities.createIconThumbnail(info.loadIcon(pm), mContext);
}
text.setText(mLabel);
@@ -126,12 +130,32 @@ public final class AddAdapter extends BaseExpandableListAdapter {
mLauncher.addShortcut(intent);
}
}
-
+
+ /**
+ * Class representing an action that will create a specific type
+ * of live folder
+ */
+ public class CreateLiveFolderAction extends CreateShortcutAction {
+ CreateLiveFolderAction(Context context, ResolveInfo info) {
+ super(context, info);
+ }
+
+ @Override
+ public void run() {
+ Intent intent = new Intent(mCreateLiveFolderIntent);
+ ActivityInfo activityInfo = mInfo.activityInfo;
+ intent.setComponent(new ComponentName(activityInfo.applicationInfo.packageName,
+ activityInfo.name));
+ mLauncher.addLiveFolder(intent);
+ }
+ }
+
/**
* Class representing an action that will add a folder
*/
public class CreateFolderAction extends AddAction {
-
+ private Drawable mIcon;
+
CreateFolderAction(Context context) {
super(context);
}
@@ -140,8 +164,8 @@ public final class AddAdapter extends BaseExpandableListAdapter {
public void bindView(View view) {
TextView text = (TextView) view;
text.setText(R.string.add_folder);
- text.setCompoundDrawablesWithIntrinsicBounds(getIcon(R.drawable.ic_launcher_folder),
- null, null, null);
+ if (mIcon == null) mIcon = getIcon(R.drawable.ic_launcher_folder);
+ text.setCompoundDrawablesWithIntrinsicBounds(mIcon, null, null, null);
}
public void run() {
@@ -175,6 +199,8 @@ public final class AddAdapter extends BaseExpandableListAdapter {
* Class representing an action that will add a PhotoFrame
*/
public class CreatePhotoFrameAction extends AddAction {
+ private Drawable mIcon;
+
CreatePhotoFrameAction(Context context) {
super(context);
}
@@ -183,8 +209,8 @@ public final class AddAdapter extends BaseExpandableListAdapter {
public void bindView(View view) {
TextView text = (TextView) view;
text.setText(R.string.add_photo_frame);
- Drawable icon = getIcon(R.drawable.ic_launcher_gallery);
- text.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
+ if (mIcon == null) mIcon = getIcon(R.drawable.ic_launcher_gallery);
+ text.setCompoundDrawablesWithIntrinsicBounds(mIcon, null, null, null);
}
public void run() {
@@ -197,6 +223,8 @@ public final class AddAdapter extends BaseExpandableListAdapter {
* Class representing an action that will add a Search widget
*/
public class CreateSearchAction extends AddAction {
+ private Drawable mIcon;
+
CreateSearchAction(Context context) {
super(context);
}
@@ -205,8 +233,8 @@ public final class AddAdapter extends BaseExpandableListAdapter {
public void bindView(View view) {
TextView text = (TextView) view;
text.setText(R.string.add_search);
- Drawable icon = getIcon(R.drawable.ic_search_gadget);
- text.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
+ if (mIcon == null) mIcon = getIcon(R.drawable.ic_search_gadget);
+ text.setCompoundDrawablesWithIntrinsicBounds(mIcon, null, null, null);
}
public void run() {
@@ -296,22 +324,27 @@ public final class AddAdapter extends BaseExpandableListAdapter {
mCreateShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
mCreateShortcutIntent.setComponent(null);
+ mCreateLiveFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
+ mCreateLiveFolderIntent.setComponent(null);
+
mSetWallpaperIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
mSetWallpaperIntent.setComponent(null);
mLauncher = launcher;
mInflater = (LayoutInflater) launcher.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mGroups = new Group[forFolder ? 2 : 4];
+ mGroups = new Group[forFolder ? 2 : 5];
final Group[] groups = mGroups;
groups[GROUP_APPLICATIONS] = new ApplicationsGroup(mLauncher,
mLauncher.getString(R.string.group_applications));
groups[GROUP_SHORTCUTS] = new Group(mLauncher.getString(R.string.group_shortcuts));
+ groups[GROUP_LIVE_FOLDERS] = new Group(mLauncher.getString(R.string.group_live_folders));
if (!forFolder) {
groups[GROUP_WALLPAPERS] = new Group(mLauncher.getString(R.string.group_wallpapers));
groups[GROUP_SHORTCUTS].add(new CreateFolderAction(launcher));
groups[GROUP_WIDGETS] = new Group(mLauncher.getString(R.string.group_widgets));
+
final Group widgets = groups[GROUP_WIDGETS];
widgets.add(new CreateClockAction(launcher));
widgets.add(new CreatePhotoFrameAction(launcher));
@@ -330,6 +363,16 @@ public final class AddAdapter extends BaseExpandableListAdapter {
}
}
+ list = findTargetsForIntent(mCreateLiveFolderIntent, packageManager);
+ if (list != null && list.size() > 0) {
+ int count = list.size();
+ final Group shortcuts = groups[GROUP_LIVE_FOLDERS];
+ for (int i = 0; i < count; i++) {
+ ResolveInfo resolveInfo = list.get(i);
+ shortcuts.add(new CreateLiveFolderAction(launcher, resolveInfo));
+ }
+ }
+
list = findTargetsForIntent(mSetWallpaperIntent, packageManager);
if (list != null && list.size() > 0) {
int count = list.size();
diff --git a/src/com/android/launcher/ApplicationInfo.java b/src/com/android/launcher/ApplicationInfo.java
index ec1c85afc..9bc09507e 100644
--- a/src/com/android/launcher/ApplicationInfo.java
+++ b/src/com/android/launcher/ApplicationInfo.java
@@ -20,9 +20,7 @@ import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import com.android.internal.provider.Settings;
/**
* Represents a launchable application. An application is made of a name (or title),
@@ -63,7 +61,7 @@ class ApplicationInfo extends ItemInfo {
Intent.ShortcutIconResource iconResource;
ApplicationInfo() {
- itemType = Settings.Favorites.ITEM_TYPE_SHORTCUT;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
}
public ApplicationInfo(ApplicationInfo info) {
@@ -82,7 +80,7 @@ class ApplicationInfo extends ItemInfo {
/**
* Creates the application intent based on a component name and various launch flags.
- * Sets {@link #itemType} to {@link Settings.Favorites#ITEM_TYPE_APPLICATION}.
+ * Sets {@link #itemType} to {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION}.
*
* @param className the class name of the component representing the intent
* @param launchFlags the launch flags
@@ -92,7 +90,7 @@ class ApplicationInfo extends ItemInfo {
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);
intent.setFlags(launchFlags);
- itemType = Settings.Favorites.ITEM_TYPE_APPLICATION;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
@Override
@@ -100,20 +98,22 @@ class ApplicationInfo extends ItemInfo {
super.onAddToDatabase(values);
String titleStr = title != null ? title.toString() : null;
- values.put(Settings.Favorites.TITLE, titleStr);
+ values.put(LauncherSettings.Favorites.TITLE, titleStr);
String uri = intent != null ? intent.toURI() : null;
- values.put(Settings.Favorites.INTENT, uri);
+ values.put(LauncherSettings.Favorites.INTENT, uri);
if (customIcon) {
- values.put(Settings.Favorites.ICON_TYPE, Settings.Favorites.ICON_TYPE_BITMAP);
- Bitmap bitmap = ((BitmapDrawable) icon).getBitmap();
+ values.put(LauncherSettings.Favorites.ICON_TYPE,
+ LauncherSettings.Favorites.ICON_TYPE_BITMAP);
+ Bitmap bitmap = ((FastBitmapDrawable) icon).getBitmap();
writeBitmap(values, bitmap);
} else {
- values.put(Settings.Favorites.ICON_TYPE, Settings.Favorites.ICON_TYPE_RESOURCE);
+ values.put(LauncherSettings.Favorites.ICON_TYPE,
+ LauncherSettings.Favorites.ICON_TYPE_RESOURCE);
if (iconResource != null) {
- values.put(Settings.Favorites.ICON_PACKAGE, iconResource.packageName);
- values.put(Settings.Favorites.ICON_RESOURCE, iconResource.resourceName);
+ values.put(LauncherSettings.Favorites.ICON_PACKAGE, iconResource.packageName);
+ values.put(LauncherSettings.Favorites.ICON_RESOURCE, iconResource.resourceName);
}
}
}
diff --git a/src/com/android/launcher/BubbleTextView.java b/src/com/android/launcher/BubbleTextView.java
index 730e08e7d..f2c31e93f 100644
--- a/src/com/android/launcher/BubbleTextView.java
+++ b/src/com/android/launcher/BubbleTextView.java
@@ -22,7 +22,7 @@ import android.util.AttributeSet;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
-import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.text.Layout;
/**
@@ -38,6 +38,9 @@ public class BubbleTextView extends TextView {
private final RectF mRect = new RectF();
private Paint mPaint;
+ private boolean mBackgroundSizeChanged;
+ private Drawable mBackground;
+
public BubbleTextView(Context context) {
super(context);
init();
@@ -55,13 +58,57 @@ public class BubbleTextView extends TextView {
private void init() {
setFocusable(true);
+ mBackground = getBackground();
+ setBackgroundDrawable(null);
+ mBackground.setCallback(this);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(getContext().getResources().getColor(R.color.bubble_dark_background));
}
@Override
- public void onDraw(Canvas canvas) {
+ protected boolean setFrame(int left, int top, int right, int bottom) {
+ if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
+ mBackgroundSizeChanged = true;
+ }
+ return super.setFrame(left, top, right, bottom);
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return who == mBackground || super.verifyDrawable(who);
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ Drawable d = mBackground;
+ if (d != null && d.isStateful()) {
+ d.setState(getDrawableState());
+ }
+ super.drawableStateChanged();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Drawable background = mBackground;
+ if (background != null) {
+ final int scrollX = mScrollX;
+ final int scrollY = mScrollY;
+
+ if (mBackgroundSizeChanged) {
+ background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+ mBackgroundSizeChanged = false;
+ }
+
+ if ((scrollX | scrollY) == 0) {
+ background.draw(canvas);
+ } else {
+ canvas.translate(scrollX, scrollY);
+ background.draw(canvas);
+ canvas.translate(-scrollX, -scrollY);
+ }
+ }
+
final Layout layout = getLayout();
final RectF rect = mRect;
final int left = getCompoundPaddingLeft();
@@ -69,10 +116,10 @@ public class BubbleTextView extends TextView {
rect.set(left + layout.getLineLeft(0) - PADDING_H,
top + layout.getLineTop(0) - PADDING_V,
- left + layout.getLineRight(0) + PADDING_H,
+ Math.min(left + layout.getLineRight(0) + PADDING_H, mScrollX + mRight - mLeft),
top + layout.getLineBottom(0) + PADDING_V);
canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, mPaint);
- super.onDraw(canvas);
+ super.draw(canvas);
}
}
diff --git a/src/com/android/launcher/CellLayout.java b/src/com/android/launcher/CellLayout.java
index 03cf7fcef..02646bff9 100644
--- a/src/com/android/launcher/CellLayout.java
+++ b/src/com/android/launcher/CellLayout.java
@@ -105,6 +105,17 @@ public class CellLayout extends ViewGroup {
}
@Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ // Generate an id for each view, this assumes we have at most 256x256 cells
+ // per workspace screen
+ final LayoutParams cellParams = (LayoutParams) params;
+ child.setId(((getId() & 0xFF) << 16) |
+ (cellParams.cellX & 0xFF) << 8 | (cellParams.cellY & 0xFF));
+
+ super.addView(child, index, params);
+ }
+
+ @Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
if (child != null) {
diff --git a/src/com/android/launcher/DeleteZone.java b/src/com/android/launcher/DeleteZone.java
index ab2b89136..798cf0de8 100644
--- a/src/com/android/launcher/DeleteZone.java
+++ b/src/com/android/launcher/DeleteZone.java
@@ -20,7 +20,6 @@ import android.widget.ImageView;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import com.android.internal.provider.Settings;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation;
@@ -35,6 +34,8 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
private static final int TRANSITION_DURATION = 250;
private static final int ANIMATION_DURATION = 200;
+ private final int[] mLocation = new int[2];
+
private Launcher mLauncher;
private boolean mTrashMode;
@@ -74,15 +75,16 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
Object dragInfo) {
- final ItemInfo item = (ItemInfo) dragInfo;
- // Accept anything except items in the all apps folder
- return item.container != ItemInfo.NO_ID;
+ return true;
}
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
+
+ if (item.container == -1) return;
+
final LauncherModel model = Launcher.getModel();
- if (item.container == Settings.Favorites.CONTAINER_DESKTOP) {
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
model.removeDesktopItem(item);
} else {
if (source instanceof UserFolder) {
@@ -115,7 +117,7 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
public void onDragStart(View v, DragSource source, Object info, int dragAction) {
final ItemInfo item = (ItemInfo) info;
- if (item != null && item.container != ItemInfo.NO_ID) {
+ if (item != null) {
mTrashMode = true;
createAnimations();
final int[] location = mLocation;
diff --git a/src/com/android/launcher/FastBitmapDrawable.java b/src/com/android/launcher/FastBitmapDrawable.java
new file mode 100644
index 000000000..170f1adc3
--- /dev/null
+++ b/src/com/android/launcher/FastBitmapDrawable.java
@@ -0,0 +1,73 @@
+/*
+ * 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.android.launcher;
+
+import android.graphics.drawable.Drawable;
+import android.graphics.PixelFormat;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+
+class FastBitmapDrawable extends Drawable {
+ private Bitmap mBitmap;
+
+ FastBitmapDrawable(Bitmap b) {
+ mBitmap = b;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawBitmap(mBitmap, 0.0f, 0.0f, null);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mBitmap.getWidth();
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mBitmap.getHeight();
+ }
+
+ @Override
+ public int getMinimumWidth() {
+ return mBitmap.getWidth();
+ }
+
+ @Override
+ public int getMinimumHeight() {
+ return mBitmap.getHeight();
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+}
diff --git a/src/com/android/launcher/Folder.java b/src/com/android/launcher/Folder.java
index 1a91eb134..bcbccf71b 100644
--- a/src/com/android/launcher/Folder.java
+++ b/src/com/android/launcher/Folder.java
@@ -21,10 +21,10 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.GridView;
import android.widget.LinearLayout;
+import android.widget.AbsListView;
+import android.widget.ListAdapter;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
@@ -34,7 +34,7 @@ import android.widget.AdapterView.OnItemLongClickListener;
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
OnItemClickListener, OnClickListener, View.OnLongClickListener {
- protected GridView mContent;
+ protected AbsListView mContent;
protected DragController mDragger;
protected Launcher mLauncher;
@@ -64,7 +64,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
protected void onFinishInflate() {
super.onFinishInflate();
- mContent = (GridView) findViewById(R.id.content);
+ mContent = (AbsListView) findViewById(R.id.content);
mContent.setOnItemClickListener(this);
mContent.setOnItemLongClickListener(this);
@@ -83,7 +83,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public boolean onLongClick(View v) {
- return false;
+ mLauncher.closeFolder(this);
+ mLauncher.showRenameDialog(mInfo);
+ return true;
}
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
@@ -120,7 +122,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
*
* @param adapter The list of applications to display in the folder.
*/
- void setContentAdapter(ArrayAdapter<ApplicationInfo> adapter) {
+ void setContentAdapter(ListAdapter adapter) {
mContent.setAdapter(adapter);
}
@@ -145,4 +147,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
final Workspace workspace = mLauncher.getWorkspace();
workspace.getChildAt(workspace.getCurrentScreen()).requestFocus();
}
+
+ void bind(FolderInfo info) {
+ mInfo = info;
+ mCloseButton.setText(info.title);
+ }
}
diff --git a/src/com/android/launcher/FolderIcon.java b/src/com/android/launcher/FolderIcon.java
index d7c623d5a..667f92ee1 100644
--- a/src/com/android/launcher/FolderIcon.java
+++ b/src/com/android/launcher/FolderIcon.java
@@ -19,7 +19,6 @@ package com.android.launcher;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
-import com.android.internal.provider.Settings;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
@@ -65,8 +64,8 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
final int itemType = item.itemType;
- return (itemType == Settings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == Settings.Favorites.ITEM_TYPE_SHORTCUT)
+ return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
&& item.container != mInfo.id;
}
diff --git a/src/com/android/launcher/FolderInfo.java b/src/com/android/launcher/FolderInfo.java
index b226b625a..a58675b0b 100644
--- a/src/com/android/launcher/FolderInfo.java
+++ b/src/com/android/launcher/FolderInfo.java
@@ -26,4 +26,9 @@ class FolderInfo extends ItemInfo {
* Whether this folder has been opened
*/
boolean opened;
+
+ /**
+ * The folder name.
+ */
+ CharSequence title;
}
diff --git a/src/com/android/launcher/HandleView.java b/src/com/android/launcher/HandleView.java
new file mode 100644
index 000000000..437d559b7
--- /dev/null
+++ b/src/com/android/launcher/HandleView.java
@@ -0,0 +1,91 @@
+/*
+ * 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.android.launcher;
+
+import android.widget.ImageView;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.KeyEvent;
+
+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();
+ }
+
+ @Override
+ public View focusSearch(int direction) {
+ View newFocus = super.focusSearch(direction);
+ if (newFocus == null) {
+ final Workspace workspace = mLauncher.getWorkspace();
+ workspace.dispatchUnhandledMove(null, direction);
+ return (mOrientation == ORIENTATION_HORIZONTAL && direction == FOCUS_DOWN) ?
+ this : workspace;
+ }
+ return newFocus;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ final boolean handled = super.onKeyDown(keyCode, event);
+
+ if (!handled && !mLauncher.isDrawerDown() && !isDirectionKey(keyCode)) {
+ return mLauncher.getApplicationsGrid().onKeyDown(keyCode, event);
+ }
+
+ return handled;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ final boolean handled = super.onKeyUp(keyCode, event);
+
+ if (!handled && !mLauncher.isDrawerDown() && !isDirectionKey(keyCode)) {
+ return mLauncher.getApplicationsGrid().onKeyUp(keyCode, event);
+ }
+
+ return handled;
+ }
+
+ private static boolean isDirectionKey(int keyCode) {
+ return keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_LEFT ||
+ keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_UP;
+ }
+
+ void setLauncher(Launcher launcher) {
+ mLauncher = launcher;
+ }
+}
diff --git a/src/com/android/launcher/InstallShortcutReceiver.java b/src/com/android/launcher/InstallShortcutReceiver.java
index d99e2b483..a1e954a05 100644
--- a/src/com/android/launcher/InstallShortcutReceiver.java
+++ b/src/com/android/launcher/InstallShortcutReceiver.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.ContentResolver;
import android.database.Cursor;
-import com.android.internal.provider.Settings;
public class InstallShortcutReceiver extends BroadcastReceiver {
private final int[] mCoordinates = new int[2];
@@ -29,6 +28,15 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent data) {
int screen = Launcher.getScreen();
+ if (!installShortcut(context, data, screen)) {
+ // The target screen is full, let's try the other screens
+ for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {
+ if (i != screen && installShortcut(context, data, i)) break;
+ }
+ }
+ }
+
+ private boolean installShortcut(Context context, Intent data, int screen) {
if (findEmptyCell(context, mCoordinates, screen)) {
CellLayout.CellInfo cell = new CellLayout.CellInfo();
cell.cellX = mCoordinates[0];
@@ -48,7 +56,11 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
Launcher.addShortcut(context, data, cell, true);
}
+
+ return true;
}
+
+ return false;
}
private static boolean findEmptyCell(Context context, int[] xy, int screen) {
@@ -58,14 +70,16 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
boolean[][] occupied = new boolean[xCount][yCount];
final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(Settings.Favorites.CONTENT_URI,
- new String[] { "cellX", "cellY", "spanX", "spanY" }, "screen=?",
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[] { LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
+ LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY },
+ LauncherSettings.Favorites.SCREEN + "=?",
new String[] { String.valueOf(screen) }, null);
- final int cellXIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLY);
- final int spanXIndex = c.getColumnIndexOrThrow(Settings.Favorites.SPANX);
- final int spanYIndex = c.getColumnIndexOrThrow(Settings.Favorites.SPANY);
+ final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
+ final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
try {
while (c.moveToNext()) {
diff --git a/src/com/android/launcher/ItemInfo.java b/src/com/android/launcher/ItemInfo.java
index f2ce23d32..61745dda0 100644
--- a/src/com/android/launcher/ItemInfo.java
+++ b/src/com/android/launcher/ItemInfo.java
@@ -21,10 +21,8 @@ import java.io.IOException;
import android.content.ContentValues;
import android.graphics.Bitmap;
-import com.android.internal.provider.Settings;
import android.util.Log;
-
/**
* Represents an item in the launcher.
*/
@@ -38,18 +36,18 @@ class ItemInfo {
long id = NO_ID;
/**
- * One of {@link Settings.Favorites#ITEM_TYPE_APPLICATION},
- * {@link Settings.Favorites#ITEM_TYPE_SHORTCUT},
- * {@link Settings.Favorites#ITEM_TYPE_USER_FOLDER},
- * {@link Settings.Favorites#ITEM_TYPE_WIDGET_CLOCK},
- * {@link Settings.Favorites#ITEM_TYPE_WIDGET_SEARCH} or
- * {@link Settings.Favorites#ITEM_TYPE_WIDGET_PHOTO_FRAME},
+ * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_USER_FOLDER},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_WIDGET_CLOCK},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_WIDGET_SEARCH} or
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_WIDGET_PHOTO_FRAME},
*/
int itemType;
/**
* The id of the container that holds this item. For the desktop, this will be
- * {@link Settings.Favorites#CONTAINER_DESKTOP}. For the all applications folder it
+ * {@link LauncherSettings.Favorites#CONTAINER_DESKTOP}. For the all applications folder it
* will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders
* it will be the id of the folder.
*/
@@ -100,13 +98,13 @@ class ItemInfo {
* @param values
*/
void onAddToDatabase(ContentValues values) {
- values.put(Settings.Favorites.ITEM_TYPE, itemType);
- values.put(Settings.Favorites.CONTAINER, container);
- values.put(Settings.Favorites.SCREEN, screen);
- values.put(Settings.Favorites.CELLX, cellX);
- values.put(Settings.Favorites.CELLY, cellY);
- values.put(Settings.Favorites.SPANX, spanX);
- values.put(Settings.Favorites.SPANY, spanY);
+ values.put(LauncherSettings.Favorites.ITEM_TYPE, itemType);
+ values.put(LauncherSettings.Favorites.CONTAINER, container);
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ values.put(LauncherSettings.Favorites.CELLX, cellX);
+ values.put(LauncherSettings.Favorites.CELLY, cellY);
+ values.put(LauncherSettings.Favorites.SPANX, spanX);
+ values.put(LauncherSettings.Favorites.SPANY, spanY);
}
static void writeBitmap(ContentValues values, Bitmap bitmap) {
@@ -120,7 +118,7 @@ class ItemInfo {
out.flush();
out.close();
- values.put(Settings.Favorites.ICON, out.toByteArray());
+ values.put(LauncherSettings.Favorites.ICON, out.toByteArray());
} catch (IOException e) {
Log.w("Favorite", "Could not write icon");
}
diff --git a/src/com/android/launcher/Launcher.java b/src/com/android/launcher/Launcher.java
index 2ae50377c..928f4caec 100644
--- a/src/com/android/launcher/Launcher.java
+++ b/src/com/android/launcher/Launcher.java
@@ -29,16 +29,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
-import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
-import android.hardware.SensorListener;
-import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -46,15 +45,12 @@ import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.provider.Contacts;
+import android.provider.*;
import android.telephony.PhoneNumberUtils;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
-import android.util.Config;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
@@ -66,14 +62,15 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.View.OnLongClickListener;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
+import android.widget.GridView;
import android.app.IWallpaperService;
-import com.android.internal.provider.Settings;
import com.android.internal.widget.SlidingDrawer;
import java.lang.ref.WeakReference;
@@ -88,18 +85,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private static final boolean PROFILE_STARTUP = false;
private static final boolean DEBUG_USER_INTERFACE = false;
- private static final String USE_OPENGL_BY_DEFAULT = "false";
-
private static final boolean REMOVE_SHORTCUT_ON_PACKAGE_REMOVE = false;
- // Type: boolean
- private static final String PROPERTY_USE_OPENGL = "launcher.opengl";
- // Type: boolean
- private static final String PROPERTY_USE_SENSORS = "launcher.sensors";
-
- private static final boolean USE_OPENGL = true;
- private static final boolean USE_SENSORS = false;
-
private static final int WALLPAPER_SCREENS_SPAN = 2;
private static final int MENU_GROUP_ADD = 1;
@@ -112,9 +99,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CHOOSE_PHOTO = 2;
private static final int REQUEST_UPDATE_PHOTO = 3;
+ private static final int REQUEST_CREATE_LIVE_FOLDER = 4;
static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
+ static final int SCREEN_COUNT = 3;
static final int DEFAULT_SCREN = 1;
static final int NUMBER_CELLS_X = 4;
static final int NUMBER_CELLS_Y = 4;
@@ -122,6 +111,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private static final int DIALOG_CREATE_SHORTCUT = 1;
static final int DIALOG_RENAME_FOLDER = 2;
+ private static final String PREFERENCES = "launcher";
+ private static final String KEY_LOCALE = "locale";
+ private static final String KEY_MCC = "mcc";
+ private static final String KEY_MNC = "mnc";
+
// Type: int
private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen";
// Type: boolean
@@ -165,19 +159,15 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private final BroadcastReceiver mApplicationsReceiver = new ApplicationsIntentReceiver();
private final ContentObserver mObserver = new FavoritesChangeObserver();
- private final Handler mHandler = new Handler();
private LayoutInflater mInflater;
- private SensorManager mSensorManager;
- private SensorHandler mSensorHandler;
-
private DragLayer mDragLayer;
private Workspace mWorkspace;
private CellLayout.CellInfo mAddItemCellInfo;
private CellLayout.CellInfo mMenuAddInfo;
private final int[] mCellCoordinates = new int[2];
- private UserFolderInfo mFolderInfo;
+ private FolderInfo mFolderInfo;
private SlidingDrawer mDrawer;
private TransitionDrawable mHandleIcon;
@@ -192,11 +182,10 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private boolean mRestoring;
private boolean mWaitingForResult;
+ private boolean mLocaleChanged;
@Override
protected void onCreate(Bundle savedInstanceState) {
- dalvik.system.VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024);
-
super.onCreate(savedInstanceState);
mInflater = getLayoutInflater();
@@ -204,11 +193,9 @@ public final class Launcher extends Activity implements View.OnClickListener, On
android.os.Debug.startMethodTracing("/sdcard/launcher");
}
+ checkForLocaleChange();
setWallpaperDimension();
- enableSensors();
- enableOpenGL();
-
if (sModel == null) {
sModel = new LauncherModel();
}
@@ -234,6 +221,30 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mDefaultKeySsb = new SpannableStringBuilder();
Selection.setSelection(mDefaultKeySsb, 0);
}
+
+ private void checkForLocaleChange() {
+ final SharedPreferences preferences = getSharedPreferences(PREFERENCES, MODE_PRIVATE);
+ final Configuration configuration = getResources().getConfiguration();
+
+ final String previousLocale = preferences.getString(KEY_LOCALE, null);
+ final String locale = configuration.locale.toString();
+
+ final int previousMcc = preferences.getInt(KEY_MCC, -1);
+ final int mcc = configuration.mcc;
+
+ final int previousMnc = preferences.getInt(KEY_MNC, -1);
+ final int mnc = configuration.mnc;
+
+ mLocaleChanged = !locale.equals(previousLocale) || mcc != previousMcc || mnc != previousMnc;
+
+ if (mLocaleChanged) {
+ final SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(KEY_LOCALE, locale);
+ editor.putInt(KEY_MCC, mcc);
+ editor.putInt(KEY_MNC, mnc);
+ editor.commit();
+ }
+ }
static int getScreen() {
synchronized (sLock) {
@@ -248,19 +259,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
private void startLoaders() {
- sModel.loadApplications(true, this);
- sModel.loadUserItems(true, this);
+ sModel.loadApplications(true, this, mLocaleChanged);
+ sModel.loadUserItems(!mLocaleChanged, this, mLocaleChanged);
mRestoring = false;
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- // When MMC/MNC changes, so can applications, so we reload them
- sModel.loadApplications(false, Launcher.this);
- }
-
private void setWallpaperDimension() {
IBinder binder = ServiceManager.getService(WALLPAPER_SERVICE);
IWallpaperService wallpaperService = IWallpaperService.Stub.asInterface(binder);
@@ -277,31 +280,6 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
}
- private void enableSensors() {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (USE_SENSORS || "true".equals(SystemProperties.get(PROPERTY_USE_SENSORS, "false"))) {
- if (Config.LOGD) {
- Log.d(LOG_TAG, "Launcher activating sensors");
- }
- mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
- mSensorHandler = new SensorHandler();
- }
- }
-
- private void enableOpenGL() {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (USE_OPENGL && "true".equals(SystemProperties.get(PROPERTY_USE_OPENGL,
- USE_OPENGL_BY_DEFAULT))) {
- if (Config.LOGD) {
- Log.d(LOG_TAG, "Launcher starting in OpenGL");
- }
- //requestWindowFeature(Window.FEATURE_OPENGL);
- //sOpenGlEnabled = true;
- } else {
- sOpenGlEnabled = false;
- }
- }
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
@@ -315,6 +293,9 @@ public final class Launcher extends Activity implements View.OnClickListener, On
case REQUEST_UPDATE_PHOTO:
completeUpdatePhotoFrame(data, mAddItemCellInfo);
break;
+ case REQUEST_CREATE_LIVE_FOLDER:
+ completeAddLiveFolder(data, mAddItemCellInfo, !mDesktopLocked);
+ break;
}
}
mWaitingForResult = false;
@@ -327,19 +308,6 @@ public final class Launcher extends Activity implements View.OnClickListener, On
if (mRestoring) {
startLoaders();
}
-
- if (mSensorManager != null) {
- mSensorManager.registerListener(mSensorHandler, SensorManager.SENSOR_ACCELEROMETER);
- }
- }
-
- @Override
- protected void onStop() {
- if (mSensorManager != null) {
- mSensorManager.unregisterListener(mSensorHandler);
- }
-
- super.onStop();
}
@Override
@@ -347,6 +315,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
boolean handled = super.onKeyUp(keyCode, event);
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
handled = mWorkspace.snapToSearch();
+ if (handled) closeDrawer(true);
}
return handled;
}
@@ -455,7 +424,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
final DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
- final ImageView handleIcon = (ImageView) drawer.findViewById(R.id.all_apps);
+ final HandleView handleIcon = (HandleView) drawer.findViewById(R.id.all_apps);
+ handleIcon.setLauncher(this);
mHandleIcon = (TransitionDrawable) handleIcon.getDrawable();
mHandleIcon.setCrossFadeEnabled(true);
@@ -577,7 +547,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
Intent.ShortcutIconResource iconResource = null;
if (bitmap != null) {
- icon = new BitmapDrawable(Utilities.createBitmapThumbnail(bitmap, context));
+ icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, context));
filtered = true;
customIcon = true;
} else {
@@ -608,7 +578,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
info.customIcon = customIcon;
info.iconResource = iconResource;
- LauncherModel.addItemToDatabase(context, info, Settings.Favorites.CONTAINER_DESKTOP,
+ LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
return info;
}
@@ -630,7 +600,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
final int[] xy = mCellCoordinates;
if (!findSlot(cellInfo, xy, info.spanX, info.spanY)) return;
- LauncherModel.addItemToDatabase(this, info, Settings.Favorites.CONTAINER_DESKTOP,
+ LauncherModel.addItemToDatabase(this, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
mWorkspace.getCurrentScreen(), xy[0], xy[1], false);
if (!mRestoring) {
@@ -746,6 +716,12 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mWorkspace.moveToDefaultScreen();
}
closeDrawer();
+ View v = getWindow().peekDecorView();
+ if (v != null && v.getWindowToken() != null) {
+ InputMethodManager imm = (InputMethodManager)getSystemService(
+ INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(v.getWindowToken());
+ }
} else {
closeDrawer(false);
}
@@ -818,6 +794,16 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
@Override
+ public void startSearch(String initialQuery, boolean selectInitialQuery,
+ Bundle appSearchData, boolean globalSearch) {
+ if (appSearchData == null) {
+ appSearchData = new Bundle();
+ appSearchData.putString(SearchManager.SOURCE, "launcher-search");
+ }
+ super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
+ }
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
if (mDesktopLocked) return false;
@@ -893,6 +879,10 @@ public final class Launcher extends Activity implements View.OnClickListener, On
startActivityForResult(intent, REQUEST_CREATE_SHORTCUT);
}
+ void addLiveFolder(Intent intent) {
+ startActivityForResult(intent, REQUEST_CREATE_LIVE_FOLDER);
+ }
+
void addFolder() {
UserFolderInfo folderInfo = new UserFolderInfo();
folderInfo.title = getText(R.string.folder_name);
@@ -900,10 +890,10 @@ public final class Launcher extends Activity implements View.OnClickListener, On
int cellY = mAddItemCellInfo.cellY;
// Update the model
- LauncherModel.addItemToDatabase(this, folderInfo, Settings.Favorites.CONTAINER_DESKTOP,
+ LauncherModel.addItemToDatabase(this, folderInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP,
mWorkspace.getCurrentScreen(), cellX, cellY, false);
sModel.addDesktopItem(folderInfo);
- sModel.addUserFolder(folderInfo);
+ sModel.addFolder(folderInfo);
// Create the view
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
@@ -911,6 +901,68 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mWorkspace.addInCurrentScreen(newFolder, cellX, cellY, 1, 1);
}
+ private void completeAddLiveFolder(Intent data, CellLayout.CellInfo cellInfo,
+ boolean insertAtFirst) {
+
+ cellInfo.screen = mWorkspace.getCurrentScreen();
+ final LiveFolderInfo info = addLiveFolder(this, data, cellInfo, false);
+
+ if (!mRestoring) {
+ sModel.addDesktopItem(info);
+
+ final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,
+ (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info);
+ mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1, insertAtFirst);
+ } else if (sModel.isDesktopLoaded()) {
+ sModel.addDesktopItem(info);
+ }
+ }
+
+ static LiveFolderInfo addLiveFolder(Context context, Intent data,
+ CellLayout.CellInfo cellInfo, boolean notify) {
+
+ Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT);
+ String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
+
+ Drawable icon = null;
+ boolean filtered = false;
+ Intent.ShortcutIconResource iconResource = null;
+
+ Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
+ if (extra != null && extra instanceof Intent.ShortcutIconResource) {
+ try {
+ iconResource = (Intent.ShortcutIconResource) extra;
+ final PackageManager packageManager = context.getPackageManager();
+ Resources resources = packageManager.getResourcesForApplication(
+ iconResource.packageName);
+ final int id = resources.getIdentifier(iconResource.resourceName, null, null);
+ icon = resources.getDrawable(id);
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "Could not load live folder icon: " + extra);
+ }
+ }
+
+ if (icon == null) {
+ icon = context.getResources().getDrawable(R.drawable.ic_launcher_folder);
+ }
+
+ final LiveFolderInfo info = new LiveFolderInfo();
+ info.icon = icon;
+ info.filtered = filtered;
+ info.title = name;
+ info.iconResource = iconResource;
+ info.uri = data.getData();
+ info.baseIntent = baseIntent;
+ info.displayMode = data.getIntExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,
+ LiveFolders.DISPLAY_MODE_GRID);
+
+ LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
+ sModel.addFolder(info);
+
+ return info;
+ }
+
void getPhotoForPhotoFrame() {
startActivityForResult(createPhotoPickIntent(), REQUEST_CHOOSE_PHOTO);
}
@@ -935,7 +987,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
if (!findSlot(cellInfo, xy, spanX, spanY)) return;
sModel.addDesktopItem(info);
- LauncherModel.addItemToDatabase(this, info, Settings.Favorites.CONTAINER_DESKTOP,
+ LauncherModel.addItemToDatabase(this, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
mWorkspace.getCurrentScreen(), xy[0], xy[1], false);
final View view = mInflater.inflate(info.layoutResource, null);
@@ -999,7 +1051,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
*/
private void registerContentObservers() {
ContentResolver resolver = getContentResolver();
- resolver.registerContentObserver(Settings.Favorites.CONTENT_URI, true, mObserver);
+ resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mObserver);
}
@Override
@@ -1059,7 +1111,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private void onFavoritesChanged() {
mDesktopLocked = true;
mDrawer.lock();
- sModel.loadUserItems(false, this);
+ sModel.loadUserItems(false, this, false);
}
void onDesktopItemsLoaded() {
@@ -1074,9 +1126,9 @@ public final class Launcher extends Activity implements View.OnClickListener, On
final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
if (userFolders != null) {
for (long folderId : userFolders) {
- final UserFolderInfo info = sModel.findFolderById(folderId);
+ final FolderInfo info = sModel.findFolderById(folderId);
if (info != null) {
- openUserFolder(info);
+ openFolder(info);
}
}
final Folder openFolder = mWorkspace.getOpenFolder();
@@ -1119,19 +1171,27 @@ public final class Launcher extends Activity implements View.OnClickListener, On
for (int i = 0; i < count; i++) {
final ItemInfo item = shortcuts.get(i);
switch (item.itemType) {
- case Settings.Favorites.ITEM_TYPE_APPLICATION:
- case Settings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
final View shortcut = createShortcut((ApplicationInfo) item);
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
!mDesktopLocked);
break;
- case Settings.Favorites.ITEM_TYPE_USER_FOLDER:
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()),
((UserFolderInfo) item));
workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
!mDesktopLocked);
break;
+ case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
+ final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(
+ R.layout.live_folder_icon, this,
+ (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()),
+ ((LiveFolderInfo) item));
+ workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,
+ !mDesktopLocked);
+ break;
default:
final Widget widget = (Widget)item;
final View view = createWidget(mInflater, widget);
@@ -1148,7 +1208,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
final int screen = workspace.getCurrentScreen();
View v = inflater.inflate(widget.layoutResource,
(ViewGroup) workspace.getChildAt(screen), false);
- if (widget.itemType == Settings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) {
+ if (widget.itemType == LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) {
((ImageView)v).setImageBitmap(widget.photo);
}
return v;
@@ -1169,8 +1229,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
// Open shortcut
final Intent intent = ((ApplicationInfo) tag).intent;
startActivitySafely(intent);
- } else if (tag instanceof UserFolderInfo) {
- handleFolderClick((UserFolderInfo) tag);
+ } else if (tag instanceof FolderInfo) {
+ handleFolderClick((FolderInfo) tag);
}
}
@@ -1188,7 +1248,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
// Close any open folder
closeFolder();
// Open the requested folder
- openUserFolder(folderInfo);
+ openFolder(folderInfo);
} else {
// Find the open folder...
Folder openFolder = mWorkspace.getFolderForTag(folderInfo);
@@ -1201,7 +1261,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
// Close any folder open on the current screen
closeFolder();
// Pull the folder onto this screen
- openUserFolder(folderInfo);
+ openFolder(folderInfo);
}
}
}
@@ -1226,14 +1286,22 @@ public final class Launcher extends Activity implements View.OnClickListener, On
* is animated relative to the specified View. If the View is null, no animation
* is played.
*
- * @param tag The UserFolderInfo describing the folder to open.
+ * @param folderInfo The FolderInfo describing the folder to open.
*/
- private void openUserFolder(Object tag) {
- UserFolder openFolder = UserFolder.fromXml(this);
+ private void openFolder(FolderInfo folderInfo) {
+ Folder openFolder;
+
+ if (folderInfo instanceof UserFolderInfo) {
+ openFolder = UserFolder.fromXml(this);
+ } else if (folderInfo instanceof LiveFolderInfo) {
+ openFolder = com.android.launcher.LiveFolder.fromXml(this, folderInfo);
+ } else {
+ return;
+ }
+
openFolder.setDragger(mDragLayer);
openFolder.setLauncher(this);
- UserFolderInfo folderInfo = (UserFolderInfo) tag;
openFolder.bind(folderInfo);
folderInfo.opened = true;
@@ -1299,6 +1367,10 @@ public final class Launcher extends Activity implements View.OnClickListener, On
return mWorkspace;
}
+ GridView getApplicationsGrid() {
+ return mAllAppsGrid;
+ }
+
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
@@ -1327,7 +1399,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
}
- void showRenameDialog(UserFolderInfo info) {
+ void showRenameDialog(FolderInfo info) {
mFolderInfo = info;
mWaitingForResult = true;
showDialog(DIALOG_RENAME_FOLDER);
@@ -1384,16 +1456,17 @@ public final class Launcher extends Activity implements View.OnClickListener, On
if (mDesktopLocked) {
mDrawer.lock();
- sModel.loadUserItems(false, Launcher.this);
+ sModel.loadUserItems(false, Launcher.this, false);
} else {
- final FolderIcon folderIcon = (FolderIcon) mWorkspace.getViewForTag(mFolderInfo);
+ final FolderIcon folderIcon = (FolderIcon)
+ mWorkspace.getViewForTag(mFolderInfo);
if (folderIcon != null) {
folderIcon.setText(name);
getWorkspace().requestLayout();
} else {
mDesktopLocked = true;
mDrawer.lock();
- sModel.loadUserItems(false, Launcher.this);
+ sModel.loadUserItems(false, Launcher.this, false);
}
}
}
@@ -1479,7 +1552,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
removeShortcutsForPackage(intent.getData().getSchemeSpecificPart());
}
removeDialog(DIALOG_CREATE_SHORTCUT);
- sModel.loadApplications(false, Launcher.this);
+ sModel.loadApplications(false, Launcher.this, false);
}
}
@@ -1488,7 +1561,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
*/
private class FavoritesChangeObserver extends ContentObserver {
public FavoritesChangeObserver() {
- super(mHandler);
+ super(new Handler());
}
@Override
@@ -1497,34 +1570,6 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
}
- private class SensorHandler implements SensorListener {
- private long mLastNegativeShake;
- private long mLastPositiveShake;
-
- public void onSensorChanged(int sensor, float[] values) {
- if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
- float shake = values[0];
- if (shake <= -SensorManager.STANDARD_GRAVITY) {
- mLastNegativeShake = SystemClock.uptimeMillis();
- } else if (shake >= SensorManager.STANDARD_GRAVITY) {
- mLastPositiveShake = SystemClock.uptimeMillis();
- }
-
- final long difference = mLastPositiveShake - mLastNegativeShake;
- if (difference <= -80 && difference >= -180) {
- mWorkspace.scrollLeft();
- mLastNegativeShake = mLastPositiveShake = 0;
- } else if (difference >= 80 && difference <= 180) {
- mWorkspace.scrollRight();
- mLastNegativeShake = mLastPositiveShake = 0;
- }
- }
- }
-
- public void onAccuracyChanged(int sensor, int accuracy) {
- }
- }
-
/**
* Receives intents from other applications to change the wallpaper.
*/
diff --git a/src/com/android/launcher/LauncherApplication.java b/src/com/android/launcher/LauncherApplication.java
new file mode 100644
index 000000000..d71fa19a1
--- /dev/null
+++ b/src/com/android/launcher/LauncherApplication.java
@@ -0,0 +1,29 @@
+/*
+ * 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.android.launcher;
+
+import android.app.Application;
+import dalvik.system.VMRuntime;
+
+public class LauncherApplication extends Application {
+ @Override
+ public void onCreate() {
+ VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024);
+
+ super.onCreate();
+ }
+}
diff --git a/src/com/android/launcher/LauncherModel.java b/src/com/android/launcher/LauncherModel.java
index 8375bbe55..0ef2a806b 100644
--- a/src/com/android/launcher/LauncherModel.java
+++ b/src/com/android/launcher/LauncherModel.java
@@ -30,7 +30,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
-import com.android.internal.provider.Settings;
import android.util.Log;
import java.util.ArrayList;
@@ -40,6 +39,7 @@ import java.util.List;
import java.util.Comparator;
import java.lang.ref.WeakReference;
import java.text.Collator;
+import java.net.URISyntaxException;
/**
* Maintains in-memory state of the Launcher. It is expected that there should be only one
@@ -58,7 +58,7 @@ public class LauncherModel {
private boolean mDesktopItemsLoaded;
private ArrayList<ItemInfo> mDesktopItems;
- private HashMap<Long, UserFolderInfo> mUserFolders;
+ private HashMap<Long, FolderInfo> mFolders;
private ArrayList<ApplicationInfo> mApplications;
private ApplicationsAdapter mApplicationsAdapter;
@@ -81,13 +81,13 @@ public class LauncherModel {
/**
* Loads the list of installed applications in mApplications.
*/
- void loadApplications(boolean isLaunching, Launcher launcher) {
- if (isLaunching && mApplicationsLoaded) {
+ void loadApplications(boolean isLaunching, Launcher launcher, boolean localeChanged) {
+ if (isLaunching && mApplicationsLoaded && !localeChanged) {
mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);
return;
}
- if (mApplicationsAdapter == null || isLaunching) {
+ if (mApplicationsAdapter == null || isLaunching || localeChanged) {
mApplicationsAdapter = new ApplicationsAdapter(launcher,
mApplications = new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER));
}
@@ -164,7 +164,7 @@ public class LauncherModel {
action.sort(new Comparator<ApplicationInfo>() {
public final int compare(ApplicationInfo a, ApplicationInfo b) {
- return sCollator.compare(a.title, b.title);
+ return sCollator.compare(a.title.toString(), b.title.toString());
}
});
@@ -221,7 +221,7 @@ public class LauncherModel {
* Loads all of the items on the desktop, in folders, or in the dock.
* These can be apps, shortcuts or widgets
*/
- void loadUserItems(boolean isLaunching, Launcher launcher) {
+ void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged) {
if (isLaunching && mDesktopItems != null && mDesktopItemsLoaded) {
// We have already loaded our data from the DB
launcher.onDesktopItemsLoaded();
@@ -240,19 +240,88 @@ public class LauncherModel {
}
mDesktopItemsLoaded = false;
- mDesktopItemsLoader = new DesktopItemsLoader(launcher);
+ mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged);
mDesktopLoader = new Thread(mDesktopItemsLoader, "Desktop Items Loader");
mDesktopLoader.start();
}
+ private static void updateShortcutLabels(ContentResolver resolver, PackageManager manager) {
+ final Cursor c = resolver.query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[] { LauncherSettings.Favorites.ID, LauncherSettings.Favorites.TITLE,
+ LauncherSettings.Favorites.INTENT, LauncherSettings.Favorites.ITEM_TYPE },
+ null, null, null);
+
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
+ final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+
+ // boolean changed = false;
+
+ try {
+ while (c.moveToNext()) {
+ try {
+ if (c.getInt(itemTypeIndex) != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ continue;
+ }
+
+ final String intentUri = c.getString(intentIndex);
+ if (intentUri != null) {
+ final Intent shortcut = Intent.getIntent(intentUri);
+ if (Intent.ACTION_MAIN.equals(shortcut.getAction())) {
+ final ComponentName name = shortcut.getComponent();
+ if (name != null) {
+ final ActivityInfo activityInfo = manager.getActivityInfo(name, 0);
+ final String title = c.getString(titleIndex);
+ String label = getLabel(manager, activityInfo);
+
+ if (title == null || !title.equals(label)) {
+ final ContentValues values = new ContentValues();
+ values.put(LauncherSettings.Favorites.TITLE, label);
+
+ resolver.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
+ values, "_id=?",
+ new String[] { String.valueOf(c.getLong(idIndex)) });
+
+ // changed = true;
+ }
+ }
+ }
+ }
+ } catch (URISyntaxException e) {
+ // Ignore
+ } catch (PackageManager.NameNotFoundException e) {
+ // Ignore
+ }
+ }
+ } finally {
+ c.close();
+ }
+
+ // if (changed) resolver.notifyChange(Settings.Favorites.CONTENT_URI, null);
+ }
+
+ private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
+ String label = activityInfo.loadLabel(manager).toString();
+ if (label == null) {
+ label = manager.getApplicationLabel(activityInfo.applicationInfo).toString();
+ if (label == null) {
+ label = activityInfo.name;
+ }
+ }
+ return label;
+ }
+
private class DesktopItemsLoader implements Runnable {
private volatile boolean mStopped;
private volatile boolean mRunning;
private final WeakReference<Launcher> mLauncher;
+ private boolean mLocaleChanged;
- DesktopItemsLoader(Launcher launcher) {
+ DesktopItemsLoader(Launcher launcher, boolean localeChanged) {
mLauncher = new WeakReference<Launcher>(launcher);
+ mLocaleChanged = localeChanged;
}
void stop() {
@@ -267,54 +336,61 @@ public class LauncherModel {
mRunning = true;
final Launcher launcher = mLauncher.get();
+ final ContentResolver contentResolver = launcher.getContentResolver();
+ final PackageManager manager = launcher.getPackageManager();
+
+ if (mLocaleChanged) {
+ updateShortcutLabels(contentResolver, manager);
+ }
mDesktopItems = new ArrayList<ItemInfo>();
- mUserFolders = new HashMap<Long, UserFolderInfo>();
+ mFolders = new HashMap<Long, FolderInfo>();
final ArrayList<ItemInfo> desktopItems = mDesktopItems;
- final Cursor c = launcher.getContentResolver().query(Settings.Favorites.CONTENT_URI,
- null, null, null, null);
+ final Cursor c = contentResolver.query(
+ LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
try {
- final int idIndex = c.getColumnIndexOrThrow(Settings.Favorites.ID);
- final int intentIndex = c.getColumnIndexOrThrow(Settings.Favorites.INTENT);
- final int titleIndex = c.getColumnIndexOrThrow(Settings.Favorites.TITLE);
- final int iconTypeIndex = c.getColumnIndexOrThrow(Settings.Favorites.ICON_TYPE);
- final int iconIndex = c.getColumnIndexOrThrow(Settings.Favorites.ICON);
- final int iconPackageIndex = c.getColumnIndexOrThrow(Settings.Favorites.ICON_PACKAGE);
- final int iconResourceIndex = c.getColumnIndexOrThrow(Settings.Favorites.ICON_RESOURCE);
- final int containerIndex = c.getColumnIndexOrThrow(Settings.Favorites.CONTAINER);
- final int itemTypeIndex = c.getColumnIndexOrThrow(Settings.Favorites.ITEM_TYPE);
- final int screenIndex = c.getColumnIndexOrThrow(Settings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLY);
-
- final PackageManager manager = launcher.getPackageManager();
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
+ final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+ final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+ final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
ApplicationInfo info;
String intentDescription;
Widget widgetInfo = null;
int container;
+ long id;
+ Intent intent;
- final HashMap<Long, UserFolderInfo> userFolders = mUserFolders;
+ final HashMap<Long, FolderInfo> folders = mFolders;
while (!mStopped && c.moveToNext()) {
try {
int itemType = c.getInt(itemTypeIndex);
switch (itemType) {
- case Settings.Favorites.ITEM_TYPE_APPLICATION:
- case Settings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
intentDescription = c.getString(intentIndex);
- Intent intent;
try {
intent = Intent.getIntent(intentDescription);
} catch (java.net.URISyntaxException e) {
continue;
}
- if (itemType == Settings.Favorites.ITEM_TYPE_APPLICATION) {
+ if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getApplicationInfo(manager, intent);
} else {
info = getApplicationInfoShortcut(c, launcher, iconTypeIndex,
@@ -338,22 +414,22 @@ public class LauncherModel {
info.cellY = c.getInt(cellYIndex);
switch (container) {
- case Settings.Favorites.CONTAINER_DESKTOP:
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
desktopItems.add(info);
break;
default:
// Item is in a user folder
UserFolderInfo folderInfo =
- findOrMakeFolder(userFolders, container);
+ findOrMakeUserFolder(folders, container);
folderInfo.add(info);
break;
}
}
break;
- case Settings.Favorites.ITEM_TYPE_USER_FOLDER:
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- long id = c.getLong(idIndex);
- UserFolderInfo folderInfo = findOrMakeFolder(userFolders, id);
+ id = c.getLong(idIndex);
+ UserFolderInfo folderInfo = findOrMakeUserFolder(folders, id);
folderInfo.title = c.getString(titleIndex);
@@ -365,24 +441,57 @@ public class LauncherModel {
folderInfo.cellY = c.getInt(cellYIndex);
switch (container) {
- case Settings.Favorites.CONTAINER_DESKTOP:
- desktopItems.add(folderInfo);
- break;
- default:
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+ desktopItems.add(folderInfo);
+ break;
+ }
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
+ id = c.getLong(idIndex);
+ LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(folders, id);
+
+ intentDescription = c.getString(intentIndex);
+ intent = null;
+ if (intentDescription != null) {
+ try {
+ intent = Intent.getIntent(intentDescription);
+ } catch (java.net.URISyntaxException e) {
+ // Ignore, a live folder might not have a base intent
+ }
+ }
+
+ liveFolderInfo.title = c.getString(titleIndex);
+ liveFolderInfo.id = id;
+ container = c.getInt(containerIndex);
+ liveFolderInfo.container = container;
+ liveFolderInfo.screen = c.getInt(screenIndex);
+ liveFolderInfo.cellX = c.getInt(cellXIndex);
+ liveFolderInfo.cellY = c.getInt(cellYIndex);
+ liveFolderInfo.uri = Uri.parse(c.getString(uriIndex));
+ liveFolderInfo.baseIntent = intent;
+ liveFolderInfo.displayMode = c.getInt(displayModeIndex);
+
+ loadLiveFolderIcon(launcher, c, iconTypeIndex, iconPackageIndex,
+ iconResourceIndex, liveFolderInfo);
+
+ switch (container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+ desktopItems.add(liveFolderInfo);
+ break;
}
break;
- case Settings.Favorites.ITEM_TYPE_WIDGET_CLOCK:
- case Settings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
- case Settings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME:
switch (itemType) {
- case Settings.Favorites.ITEM_TYPE_WIDGET_CLOCK:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK:
widgetInfo = Widget.makeClock();
break;
- case Settings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
widgetInfo = Widget.makeSearch();
break;
- case Settings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME:
+ case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME:
widgetInfo = Widget.makePhotoFrame();
byte[] data = c.getBlob(iconIndex);
if (data != null) {
@@ -394,7 +503,7 @@ public class LauncherModel {
if (widgetInfo != null) {
container = c.getInt(containerIndex);
- if (container != Settings.Favorites.CONTAINER_DESKTOP) {
+ if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
Log.e(Launcher.LOG_TAG, "Widget found where container "
+ "!= CONTAINER_DESKTOP -- ignoring!");
continue;
@@ -432,6 +541,33 @@ public class LauncherModel {
}
}
+ private static void loadLiveFolderIcon(Launcher launcher, Cursor c, int iconTypeIndex,
+ int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
+
+ int iconType = c.getInt(iconTypeIndex);
+ switch (iconType) {
+ case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
+ String packageName = c.getString(iconPackageIndex);
+ String resourceName = c.getString(iconResourceIndex);
+ PackageManager packageManager = launcher.getPackageManager();
+ try {
+ Resources resources = packageManager.getResourcesForApplication(packageName);
+ final int id = resources.getIdentifier(resourceName, null, null);
+ liveFolderInfo.icon = resources.getDrawable(id);
+ } catch (Exception e) {
+ liveFolderInfo.icon =
+ launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
+ }
+ liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
+ liveFolderInfo.iconResource.packageName = packageName;
+ liveFolderInfo.iconResource.resourceName = resourceName;
+ break;
+ default:
+ liveFolderInfo.icon =
+ launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
+ }
+ }
+
/**
* Finds the user folder defined by the specified id.
*
@@ -439,28 +575,42 @@ public class LauncherModel {
*
* @return A UserFolderInfo if the folder exists or null otherwise.
*/
- UserFolderInfo findFolderById(long id) {
- return mUserFolders.get(id);
+ FolderInfo findFolderById(long id) {
+ return mFolders.get(id);
}
- void addUserFolder(UserFolderInfo info) {
- mUserFolders.put(info.id, info);
+ void addFolder(FolderInfo info) {
+ mFolders.put(info.id, info);
}
/**
* Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
* new one.
*/
- private UserFolderInfo findOrMakeFolder(HashMap<Long, UserFolderInfo> userFolders, long id) {
- UserFolderInfo folderInfo;
+ private UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
// See if a placeholder was created for us already
- folderInfo = userFolders.get(id);
- if (folderInfo == null) {
+ FolderInfo folderInfo = folders.get(id);
+ if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
// No placeholder -- create a new instance
folderInfo = new UserFolderInfo();
- userFolders.put(id, folderInfo);
+ folders.put(id, folderInfo);
+ }
+ return (UserFolderInfo) folderInfo;
+ }
+
+ /**
+ * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
+ * new one.
+ */
+ private LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
+ // See if a placeholder was created for us already
+ FolderInfo folderInfo = folders.get(id);
+ if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
+ // No placeholder -- create a new instance
+ folderInfo = new LiveFolderInfo();
+ folders.put(id, folderInfo);
}
- return folderInfo;
+ return (LiveFolderInfo) folderInfo;
}
/**
@@ -483,8 +633,8 @@ public class LauncherModel {
for (int i = 0; i < count; i++) {
ItemInfo item = desktopItems.get(i);
switch (item.itemType) {
- case Settings.Favorites.ITEM_TYPE_APPLICATION:
- case Settings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
((ApplicationInfo)item).icon.setCallback(null);
}
}
@@ -562,7 +712,7 @@ public class LauncherModel {
if (info.title == null) {
info.title = "";
}
- info.itemType = Settings.Favorites.ITEM_TYPE_APPLICATION;
+ info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
return info;
}
@@ -573,11 +723,11 @@ public class LauncherModel {
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {
final ApplicationInfo info = new ApplicationInfo();
- info.itemType = Settings.Favorites.ITEM_TYPE_SHORTCUT;
+ info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
int iconType = c.getInt(iconTypeIndex);
switch (iconType) {
- case Settings.Favorites.ICON_TYPE_RESOURCE:
+ case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
String packageName = c.getString(iconPackageIndex);
String resourceName = c.getString(iconResourceIndex);
PackageManager packageManager = launcher.getPackageManager();
@@ -593,10 +743,11 @@ public class LauncherModel {
info.iconResource.resourceName = resourceName;
info.customIcon = false;
break;
- case Settings.Favorites.ICON_TYPE_BITMAP:
+ case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
byte[] data = c.getBlob(iconIndex);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- info.icon = new BitmapDrawable(Utilities.createBitmapThumbnail(bitmap, launcher));
+ info.icon = new FastBitmapDrawable(
+ Utilities.createBitmapThumbnail(bitmap, launcher));
info.filtered = true;
info.customIcon = true;
break;
@@ -621,7 +772,7 @@ public class LauncherModel {
* @param userFolderInfo
*/
void removeUserFolder(UserFolderInfo userFolderInfo) {
- mUserFolders.remove(userFolderInfo.id);
+ mFolders.remove(userFolderInfo.id);
}
/**
@@ -652,12 +803,12 @@ public class LauncherModel {
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
- values.put(Settings.Favorites.CONTAINER, item.container);
- values.put(Settings.Favorites.CELLX, item.cellX);
- values.put(Settings.Favorites.CELLY, item.cellY);
- values.put(Settings.Favorites.SCREEN, item.screen);
+ values.put(LauncherSettings.Favorites.CONTAINER, item.container);
+ values.put(LauncherSettings.Favorites.CELLX, item.cellX);
+ values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+ values.put(LauncherSettings.Favorites.SCREEN, item.screen);
- cr.update(Settings.Favorites.getContentUri(item.id, false), values, null, null);
+ cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
}
/**
@@ -666,7 +817,7 @@ public class LauncherModel {
*/
static boolean shortcutExists(Context context, String title, Intent intent) {
final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(Settings.Favorites.CONTENT_URI,
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
new String[] { "title", "intent" }, "title=? and intent=?",
new String[] { title, intent.toURI() }, null);
boolean result = false;
@@ -678,21 +829,32 @@ public class LauncherModel {
return result;
}
- UserFolderInfo getFolderById(Context context, long id) {
+ FolderInfo getFolderById(Context context, long id) {
final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(Settings.Favorites.CONTENT_URI, null, "_id=? and itemType=?",
- new String[] { String.valueOf(id),
- String.valueOf(Settings.Favorites.ITEM_TYPE_USER_FOLDER) }, null);
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
+ "_id=? and itemType=? or itemType=?",
+ new String[] { String.valueOf(id),
+ String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
+ String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);
try {
if (c.moveToFirst()) {
- final int titleIndex = c.getColumnIndexOrThrow(Settings.Favorites.TITLE);
- final int containerIndex = c.getColumnIndexOrThrow(Settings.Favorites.CONTAINER);
- final int screenIndex = c.getColumnIndexOrThrow(Settings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLY);
-
- UserFolderInfo folderInfo = findOrMakeFolder(mUserFolders, id);
+ final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+
+ FolderInfo folderInfo = null;
+ switch (c.getInt(itemTypeIndex)) {
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+ folderInfo = findOrMakeUserFolder(mFolders, id);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
+ folderInfo = findOrMakeLiveFolder(mFolders, id);
+ break;
+ }
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
@@ -712,18 +874,18 @@ public class LauncherModel {
static Widget getPhotoFrameInfo(Context context, int screen, int cellX, int cellY) {
final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(Settings.Favorites.CONTENT_URI,
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
null, "screen=? and cellX=? and cellY=? and itemType=?",
new String[] { String.valueOf(screen), String.valueOf(cellX), String.valueOf(cellY),
- String.valueOf(Settings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) }, null);
+ String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) }, null);
try {
if (c.moveToFirst()) {
- final int idIndex = c.getColumnIndexOrThrow(Settings.Favorites.ID);
- final int containerIndex = c.getColumnIndexOrThrow(Settings.Favorites.CONTAINER);
- final int screenIndex = c.getColumnIndexOrThrow(Settings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(Settings.Favorites.CELLY);
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
+ final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
Widget widgetInfo = Widget.makePhotoFrame();
widgetInfo.id = c.getLong(idIndex);
@@ -757,8 +919,8 @@ public class LauncherModel {
item.onAddToDatabase(values);
- Uri result = cr.insert(notify ? Settings.Favorites.CONTENT_URI :
- Settings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+ Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
+ LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
if (result != null) {
item.id = Integer.parseInt(result.getPathSegments().get(1));
@@ -774,7 +936,7 @@ public class LauncherModel {
item.onAddToDatabase(values);
- cr.update(Settings.Favorites.getContentUri(item.id, false), values, null, null);
+ cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
}
/**
@@ -785,7 +947,7 @@ public class LauncherModel {
static void deleteItemFromDatabase(Context context, ItemInfo item) {
final ContentResolver cr = context.getContentResolver();
- cr.delete(Settings.Favorites.getContentUri(item.id, false), null, null);
+ cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null);
}
@@ -795,8 +957,8 @@ public class LauncherModel {
static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
final ContentResolver cr = context.getContentResolver();
- cr.delete(Settings.Favorites.getContentUri(info.id, false), null, null);
- cr.delete(Settings.Favorites.CONTENT_URI, Settings.Favorites.CONTAINER + "=" + info.id,
+ cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
+ cr.delete(LauncherSettings.Favorites.CONTENT_URI, LauncherSettings.Favorites.CONTAINER + "=" + info.id,
null);
}
}
diff --git a/src/com/android/launcher/LauncherProvider.java b/src/com/android/launcher/LauncherProvider.java
new file mode 100644
index 000000000..a3e529d32
--- /dev/null
+++ b/src/com/android/launcher/LauncherProvider.java
@@ -0,0 +1,435 @@
+/*
+ * 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.android.launcher;
+
+import android.content.ContentProvider;
+import android.content.Context;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.ContentResolver;
+import android.content.pm.PackageManager;
+import android.content.pm.ActivityInfo;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.Cursor;
+import android.util.Log;
+import android.util.Xml;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.os.*;
+import android.provider.Settings;
+
+import java.io.FileReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import com.android.internal.util.XmlUtils;
+
+public class LauncherProvider extends ContentProvider {
+ private static final String LOG_TAG = "LauncherSettingsProvider";
+
+ private static final String DATABASE_NAME = "launcher.db";
+ private static final int DATABASE_VERSION = 1;
+
+ static final String AUTHORITY = "com.android.launcher.settings";
+
+ static final String TABLE_FAVORITES = "favorites";
+ static final String PARAMETER_NOTIFY = "notify";
+
+ private SQLiteOpenHelper mOpenHelper;
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ SqlArguments args = new SqlArguments(uri, null, null);
+ if (TextUtils.isEmpty(args.where)) {
+ return "vnd.android.cursor.dir/" + args.table;
+ } else {
+ return "vnd.android.cursor.item/" + args.table;
+ }
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+
+ SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(args.table);
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor result = qb.query(db, projection, args.where, args.args, null, null, sortOrder);
+ result.setNotificationUri(getContext().getContentResolver(), uri);
+
+ return result;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ SqlArguments args = new SqlArguments(uri);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ final long rowId = db.insert(args.table, null, initialValues);
+ if (rowId <= 0) return null;
+
+ uri = ContentUris.withAppendedId(uri, rowId);
+ sendNotify(uri);
+
+ return uri;
+ }
+
+ @Override
+ public int bulkInsert(Uri uri, ContentValues[] values) {
+ SqlArguments args = new SqlArguments(uri);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ int numValues = values.length;
+ for (int i = 0; i < numValues; i++) {
+ if (db.insert(args.table, null, values[i]) < 0) return 0;
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ sendNotify(uri);
+ return values.length;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count = db.delete(args.table, args.where, args.args);
+ if (count > 0) sendNotify(uri);
+
+ return count;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count = db.update(args.table, values, args.where, args.args);
+ if (count > 0) sendNotify(uri);
+
+ return count;
+ }
+
+ private void sendNotify(Uri uri) {
+ String notify = uri.getQueryParameter(PARAMETER_NOTIFY);
+ if (notify == null || "true".equals(notify)) {
+ getContext().getContentResolver().notifyChange(uri, null);
+ }
+ }
+
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+ /**
+ * Path to file containing default favorite packages, relative to ANDROID_ROOT.
+ */
+ private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml";
+
+ private static final String TAG_FAVORITES = "favorites";
+ private static final String TAG_FAVORITE = "favorite";
+ private static final String TAG_PACKAGE = "package";
+ private static final String TAG_CLASS = "class";
+
+ private static final String ATTRIBUTE_SCREEN = "screen";
+ private static final String ATTRIBUTE_X = "x";
+ private static final String ATTRIBUTE_Y = "y";
+
+ private final Context mContext;
+
+ DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE favorites (" +
+ "_id INTEGER PRIMARY KEY," +
+ "title TEXT," +
+ "intent TEXT," +
+ "container INTEGER," +
+ "screen INTEGER," +
+ "cellX INTEGER," +
+ "cellY INTEGER," +
+ "spanX INTEGER," +
+ "spanY INTEGER," +
+ "itemType INTEGER," +
+ "isShortcut INTEGER," +
+ "iconType INTEGER," +
+ "iconPackage TEXT," +
+ "iconResource TEXT," +
+ "icon BLOB," +
+ "uri TEXT," +
+ "displayMode INTEGER" +
+ ");");
+
+ if (!convertDatabase(db)) {
+ // Populate favorites table with initial favorites
+ loadFavorites(db, DEFAULT_FAVORITES_PATH);
+ }
+ }
+
+ private boolean convertDatabase(SQLiteDatabase db) {
+ boolean converted = false;
+
+ final Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
+ "/favorites?notify=true");
+ final ContentResolver resolver = mContext.getContentResolver();
+ Cursor cursor = null;
+
+ try {
+ cursor = resolver.query(uri, null, null, null, null);
+ } catch (Exception e) {
+ // Ignore
+ }
+
+ // We already have a favorites database in the old provider
+ if (cursor != null && cursor.getCount() > 0) {
+ try {
+ converted = copyFromCursor(db, cursor) > 0;
+ } finally {
+ cursor.close();
+ }
+
+ if (converted) {
+ resolver.delete(uri, null, null);
+ }
+ }
+
+ return converted;
+ }
+
+ private int copyFromCursor(SQLiteDatabase db, Cursor c) {
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
+ final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+ final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+ final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
+
+ ContentValues[] rows = new ContentValues[c.getCount()];
+ int i = 0;
+ while (c.moveToNext()) {
+ ContentValues values = new ContentValues(c.getColumnCount());
+ values.put(LauncherSettings.Favorites.ID, c.getLong(idIndex));
+ values.put(LauncherSettings.Favorites.INTENT, c.getString(intentIndex));
+ values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
+ values.put(LauncherSettings.Favorites.ICON_TYPE, c.getInt(iconTypeIndex));
+ values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
+ values.put(LauncherSettings.Favorites.ICON_PACKAGE, c.getString(iconPackageIndex));
+ values.put(LauncherSettings.Favorites.ICON_RESOURCE, c.getString(iconResourceIndex));
+ values.put(LauncherSettings.Favorites.CONTAINER, c.getInt(containerIndex));
+ values.put(LauncherSettings.Favorites.ITEM_TYPE, c.getInt(itemTypeIndex));
+ values.put(LauncherSettings.Favorites.SCREEN, c.getInt(screenIndex));
+ values.put(LauncherSettings.Favorites.CELLX, c.getInt(cellXIndex));
+ values.put(LauncherSettings.Favorites.CELLY, c.getInt(cellYIndex));
+ values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
+ values.put(LauncherSettings.Favorites.DISPLAY_MODE, c.getInt(displayModeIndex));
+ rows[i++] = values;
+ }
+
+ db.beginTransaction();
+ int total = 0;
+ try {
+ int numValues = rows.length;
+ for (i = 0; i < numValues; i++) {
+ if (db.insert(TABLE_FAVORITES, null, rows[i]) < 0) {
+ return 0;
+ } else {
+ total++;
+ }
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ return total;
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to " +
+ newVersion + ", which will destroy all old data");
+
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
+ onCreate(db);
+ }
+
+
+ /**
+ * Loads the default set of favorite packages from an xml file.
+ *
+ * @param db The database to write the values into
+ * @param subPath The relative path from ANDROID_ROOT to the file to read
+ */
+ private int loadFavorites(SQLiteDatabase db, String subPath) {
+ FileReader favReader;
+
+ // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+ final File favFile = new File(Environment.getRootDirectory(), subPath);
+ try {
+ favReader = new FileReader(favFile);
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find or open favorites file " + favFile);
+ return 0;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ ContentValues values = new ContentValues();
+
+ PackageManager packageManager = mContext.getPackageManager();
+ ActivityInfo info;
+ int i = 0;
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(favReader);
+
+ XmlUtils.beginDocument(parser, TAG_FAVORITES);
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+
+ String name = parser.getName();
+ if (!TAG_FAVORITE.equals(name)) {
+ break;
+ }
+
+ String pkg = parser.getAttributeValue(null, TAG_PACKAGE);
+ String cls = parser.getAttributeValue(null, TAG_CLASS);
+ try {
+ ComponentName cn = new ComponentName(pkg, cls);
+ info = packageManager.getActivityInfo(cn, 0);
+ intent.setComponent(cn);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ values.put(LauncherSettings.Favorites.INTENT, intent.toURI());
+ values.put(LauncherSettings.Favorites.TITLE,
+ info.loadLabel(packageManager).toString());
+ values.put(LauncherSettings.Favorites.CONTAINER,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
+ values.put(LauncherSettings.Favorites.ITEM_TYPE,
+ LauncherSettings.Favorites.ITEM_TYPE_APPLICATION);
+ values.put(LauncherSettings.Favorites.SCREEN,
+ parser.getAttributeValue(null, ATTRIBUTE_SCREEN));
+ values.put(LauncherSettings.Favorites.CELLX,
+ parser.getAttributeValue(null, ATTRIBUTE_X));
+ values.put(LauncherSettings.Favorites.CELLY,
+ parser.getAttributeValue(null, ATTRIBUTE_Y));
+ values.put(LauncherSettings.Favorites.SPANX, 1);
+ values.put(LauncherSettings.Favorites.SPANY, 1);
+ db.insert(TABLE_FAVORITES, null, values);
+ i++;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(LOG_TAG, "Unable to add favorite: " + pkg + "/" + cls, e);
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(LOG_TAG, "Got exception parsing favorites.", e);
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Got exception parsing favorites.", e);
+ }
+
+ // Add a clock
+ values.clear();
+ values.put(LauncherSettings.Favorites.CONTAINER,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
+ values.put(LauncherSettings.Favorites.ITEM_TYPE,
+ LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK);
+ values.put(LauncherSettings.Favorites.SCREEN, 1);
+ values.put(LauncherSettings.Favorites.CELLX, 1);
+ values.put(LauncherSettings.Favorites.CELLY, 0);
+ values.put(LauncherSettings.Favorites.SPANX, 2);
+ values.put(LauncherSettings.Favorites.SPANY, 2);
+ db.insert(TABLE_FAVORITES, null, values);
+
+ // Add a search box
+ values.clear();
+ values.put(LauncherSettings.Favorites.CONTAINER,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
+ values.put(LauncherSettings.Favorites.ITEM_TYPE,
+ LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH);
+ values.put(LauncherSettings.Favorites.SCREEN, 2);
+ values.put(LauncherSettings.Favorites.CELLX, 0);
+ values.put(LauncherSettings.Favorites.CELLY, 0);
+ values.put(LauncherSettings.Favorites.SPANX, 4);
+ values.put(LauncherSettings.Favorites.SPANY, 1);
+ db.insert(TABLE_FAVORITES, null, values);
+
+ return i;
+ }
+ }
+
+ static class SqlArguments {
+ public final String table;
+ public final String where;
+ public final String[] args;
+
+ SqlArguments(Uri url, String where, String[] args) {
+ if (url.getPathSegments().size() == 1) {
+ this.table = url.getPathSegments().get(0);
+ this.where = where;
+ this.args = args;
+ } else if (url.getPathSegments().size() != 2) {
+ throw new IllegalArgumentException("Invalid URI: " + url);
+ } else if (!TextUtils.isEmpty(where)) {
+ throw new UnsupportedOperationException("WHERE clause not supported: " + url);
+ } else {
+ this.table = url.getPathSegments().get(0);
+ this.where = "_id=" + ContentUris.parseId(url);
+ this.args = null;
+ }
+ }
+
+ SqlArguments(Uri url) {
+ if (url.getPathSegments().size() == 1) {
+ table = url.getPathSegments().get(0);
+ where = null;
+ args = null;
+ } else {
+ throw new IllegalArgumentException("Invalid URI: " + url);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher/LauncherSettings.java b/src/com/android/launcher/LauncherSettings.java
new file mode 100644
index 000000000..c5dfd1ff0
--- /dev/null
+++ b/src/com/android/launcher/LauncherSettings.java
@@ -0,0 +1,222 @@
+/*
+ * 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.android.launcher;
+
+import android.provider.BaseColumns;
+import android.net.Uri;
+
+/**
+ * Settings related utilities.
+ */
+class LauncherSettings {
+ /**
+ * Favorites.
+ */
+ static final class Favorites implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ static final Uri CONTENT_URI = Uri.parse("content://" +
+ LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
+ "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+
+ /**
+ * The content:// style URL for this table. When this Uri is used, no notification is
+ * sent if the content changes.
+ */
+ static final Uri CONTENT_URI_NO_NOTIFICATION = Uri.parse("content://" +
+ LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
+ "?" + LauncherProvider.PARAMETER_NOTIFY + "=false");
+
+ /**
+ * The content:// style URL for a given row, identified by its id.
+ *
+ * @param id The row id.
+ * @param notify True to send a notification is the content changes.
+ *
+ * @return The unique content URL for the specified row.
+ */
+ static Uri getContentUri(long id, boolean notify) {
+ return Uri.parse("content://" + LauncherProvider.AUTHORITY +
+ "/" + LauncherProvider.TABLE_FAVORITES + "/" + id + "?" +
+ LauncherProvider.PARAMETER_NOTIFY + "=" + notify);
+ }
+
+ /**
+ * The row ID.
+ * <p>Type: INTEGER</p>
+ */
+ static final String ID = "_id";
+
+ /**
+ * Descriptive name of the favorite that can be displayed to the user.
+ * <P>Type: TEXT</P>
+ */
+ static final String TITLE = "title";
+
+ /**
+ * The Intent URL of the favorite, describing what it points to. This
+ * value is given to {@link android.content.Intent#getIntent} to create
+ * an Intent that can be launched.
+ * <P>Type: TEXT</P>
+ */
+ static final String INTENT = "intent";
+
+ /**
+ * The container holding the favorite
+ * <P>Type: INTEGER</P>
+ */
+ static final String CONTAINER = "container";
+
+ /**
+ * The icon is a resource identified by a package name and an integer id.
+ */
+ static final int CONTAINER_DESKTOP = -100;
+
+ /**
+ * The screen holding the favorite (if container is CONTAINER_DESKTOP)
+ * <P>Type: INTEGER</P>
+ */
+ static final String SCREEN = "screen";
+
+ /**
+ * The X coordinate of the cell holding the favorite
+ * (if container is CONTAINER_DESKTOP or CONTAINER_DOCK)
+ * <P>Type: INTEGER</P>
+ */
+ static final String CELLX = "cellX";
+
+ /**
+ * The Y coordinate of the cell holding the favorite
+ * (if container is CONTAINER_DESKTOP)
+ * <P>Type: INTEGER</P>
+ */
+ static final String CELLY = "cellY";
+
+ /**
+ * The X span of the cell holding the favorite
+ * <P>Type: INTEGER</P>
+ */
+ static final String SPANX = "spanX";
+
+ /**
+ * The Y span of the cell holding the favorite
+ * <P>Type: INTEGER</P>
+ */
+ static final String SPANY = "spanY";
+
+ /**
+ * The type of the favorite
+ *
+ * <P>Type: INTEGER</P>
+ */
+ static final String ITEM_TYPE = "itemType";
+
+ /**
+ * The favorite is an application
+ */
+ static final int ITEM_TYPE_APPLICATION = 0;
+
+ /**
+ * The favorite is an application created shortcut
+ */
+ static final int ITEM_TYPE_SHORTCUT = 1;
+
+ /**
+ * The favorite is a user created folder
+ */
+ static final int ITEM_TYPE_USER_FOLDER = 2;
+
+ /**
+ * The favorite is a live folder
+ */
+ static final int ITEM_TYPE_LIVE_FOLDER = 3;
+
+ /**
+ * The favorite is a clock
+ */
+ static final int ITEM_TYPE_WIDGET_CLOCK = 1000;
+
+ /**
+ * The favorite is a search widget
+ */
+ static final int ITEM_TYPE_WIDGET_SEARCH = 1001;
+
+ /**
+ * The favorite is a photo frame
+ */
+ static final int ITEM_TYPE_WIDGET_PHOTO_FRAME = 1002;
+
+ /**
+ * Indicates whether this favorite is an application-created shortcut or not.
+ * If the value is 0, the favorite is not an application-created shortcut, if the
+ * value is 1, it is an application-created shortcut.
+ * <P>Type: INTEGER</P>
+ */
+ static final String IS_SHORTCUT = "isShortcut";
+
+ /**
+ * The icon type.
+ * <P>Type: INTEGER</P>
+ */
+ static final String ICON_TYPE = "iconType";
+
+ /**
+ * The icon is a resource identified by a package name and an integer id.
+ */
+ static final int ICON_TYPE_RESOURCE = 0;
+
+ /**
+ * The icon is a bitmap.
+ */
+ static final int ICON_TYPE_BITMAP = 1;
+
+ /**
+ * The icon package name, if icon type is ICON_TYPE_RESOURCE.
+ * <P>Type: TEXT</P>
+ */
+ static final String ICON_PACKAGE = "iconPackage";
+
+ /**
+ * The icon resource id, if icon type is ICON_TYPE_RESOURCE.
+ * <P>Type: TEXT</P>
+ */
+ static final String ICON_RESOURCE = "iconResource";
+
+ /**
+ * The custom icon bitmap, if icon type is ICON_TYPE_BITMAP.
+ * <P>Type: BLOB</P>
+ */
+ static final String ICON = "icon";
+
+ /**
+ * The URI associated with the favorite. It is used, for instance, by
+ * live folders to find the content provider.
+ * <P>Type: TEXT</P>
+ */
+ static final String URI = "uri";
+
+ /**
+ * The display mode if the item is a live folder.
+ * <P>Type: INTEGER</P>
+ *
+ * @see android.provider.LiveFolders#DISPLAY_MODE_GRID
+ * @see android.provider.LiveFolders#DISPLAY_MODE_LIST
+ */
+ static final String DISPLAY_MODE = "displayMode";
+ }
+}
diff --git a/src/com/android/launcher/LiveFolder.java b/src/com/android/launcher/LiveFolder.java
new file mode 100644
index 000000000..37b98e0f7
--- /dev/null
+++ b/src/com/android/launcher/LiveFolder.java
@@ -0,0 +1,83 @@
+/*
+ * 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.android.launcher;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.net.Uri;
+import android.provider.LiveFolders;
+
+public class LiveFolder extends Folder {
+ public LiveFolder(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ static LiveFolder fromXml(Context context, FolderInfo folderInfo) {
+ final int layout = isDisplayModeList(folderInfo) ?
+ R.layout.live_folder_list : R.layout.live_folder_grid;
+ return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
+ }
+
+ private static boolean isDisplayModeList(FolderInfo folderInfo) {
+ return ((LiveFolderInfo) folderInfo).displayMode ==
+ LiveFolders.DISPLAY_MODE_LIST;
+ }
+
+ @Override
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ LiveFolderAdapter.ViewHolder holder = (LiveFolderAdapter.ViewHolder) v.getTag();
+
+ if (holder.useBaseIntent) {
+ final Intent baseIntent = ((LiveFolderInfo) mInfo).baseIntent;
+ if (baseIntent != null) {
+ final Intent intent = new Intent(baseIntent);
+ Uri uri = baseIntent.getData();
+ uri = uri.buildUpon().appendPath(Long.toString(holder.id)).build();
+ intent.setData(uri);
+ mLauncher.startActivitySafely(intent);
+ }
+ } else if (holder.intent != null) {
+ mLauncher.startActivitySafely(holder.intent);
+ }
+ }
+
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ return false;
+ }
+
+ void bind(FolderInfo info) {
+ super.bind(info);
+ setContentAdapter(new LiveFolderAdapter(mLauncher, (LiveFolderInfo) info));
+ }
+
+ @Override
+ void onOpen() {
+ super.onOpen();
+ requestFocus();
+ }
+
+ @Override
+ void onClose() {
+ super.onClose();
+ ((LiveFolderAdapter) mContent.getAdapter()).cleanup();
+ }
+}
diff --git a/src/com/android/launcher/LiveFolderAdapter.java b/src/com/android/launcher/LiveFolderAdapter.java
new file mode 100644
index 000000000..01db5a639
--- /dev/null
+++ b/src/com/android/launcher/LiveFolderAdapter.java
@@ -0,0 +1,205 @@
+/*
+ * 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.android.launcher;
+
+import android.widget.CursorAdapter;
+import android.widget.TextView;
+import android.widget.ImageView;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.pm.PackageManager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.database.Cursor;
+import android.provider.LiveFolders;
+import android.graphics.drawable.Drawable;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.lang.ref.SoftReference;
+
+class LiveFolderAdapter extends CursorAdapter {
+ private boolean mIsList;
+ private LayoutInflater mInflater;
+
+ private final HashMap<String, Drawable> mIcons = new HashMap<String, Drawable>();
+ private final HashMap<Long, SoftReference<Drawable>> mCustomIcons =
+ new HashMap<Long, SoftReference<Drawable>>();
+ private final Launcher mLauncher;
+
+ LiveFolderAdapter(Launcher launcher, LiveFolderInfo info) {
+ super(launcher, query(launcher, info), true);
+ mIsList = info.displayMode == LiveFolders.DISPLAY_MODE_LIST;
+ mInflater = LayoutInflater.from(launcher);
+ mLauncher = launcher;
+
+ mLauncher.startManagingCursor(getCursor());
+ }
+
+ private static Cursor query(Context context, LiveFolderInfo info) {
+ return context.getContentResolver().query(info.uri, null, null, null, LiveFolders.NAME + " ASC");
+ }
+
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View view;
+ final ViewHolder holder = new ViewHolder();
+
+ if (!mIsList) {
+ view = mInflater.inflate(R.layout.application_boxed, parent, false);
+ } else {
+ view = mInflater.inflate(R.layout.application_list, parent, false);
+ holder.description = (TextView) view.findViewById(R.id.description);
+ holder.icon = (ImageView) view.findViewById(R.id.icon);
+ }
+
+ holder.name = (TextView) view.findViewById(R.id.name);
+
+ holder.idIndex = cursor.getColumnIndexOrThrow(LiveFolders._ID);
+ holder.nameIndex = cursor.getColumnIndexOrThrow(LiveFolders.NAME);
+ holder.descriptionIndex = cursor.getColumnIndex(LiveFolders.DESCRIPTION);
+ holder.intentIndex = cursor.getColumnIndex(LiveFolders.INTENT);
+ holder.iconBitmapIndex = cursor.getColumnIndex(LiveFolders.ICON_BITMAP);
+ holder.iconResourceIndex = cursor.getColumnIndex(LiveFolders.ICON_RESOURCE);
+ holder.iconPackageIndex = cursor.getColumnIndex(LiveFolders.ICON_PACKAGE);
+
+ view.setTag(holder);
+
+ return view;
+ }
+
+ public void bindView(View view, Context context, Cursor cursor) {
+ final ViewHolder holder = (ViewHolder) view.getTag();
+
+ holder.id = cursor.getLong(holder.idIndex);
+ final Drawable icon = loadIcon(context, cursor, holder);
+
+ holder.name.setText(cursor.getString(holder.nameIndex));
+
+ if (!mIsList) {
+ holder.name.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
+ } else {
+ final boolean hasIcon = icon != null;
+ holder.icon.setVisibility(hasIcon ? View.VISIBLE : View.GONE);
+ if (hasIcon) holder.icon.setImageDrawable(icon);
+
+ if (holder.descriptionIndex != -1) {
+ final String description = cursor.getString(holder.descriptionIndex);
+ if (description != null) {
+ holder.description.setText(description);
+ holder.description.setVisibility(View.VISIBLE);
+ } else {
+ holder.description.setVisibility(View.GONE);
+ }
+ } else {
+ holder.description.setVisibility(View.GONE);
+ }
+ }
+
+ if (holder.intentIndex != -1) {
+ try {
+ holder.intent = Intent.getIntent(cursor.getString(holder.intentIndex));
+ } catch (URISyntaxException e) {
+ // Ignore
+ }
+ } else {
+ holder.useBaseIntent = true;
+ }
+ }
+
+ private Drawable loadIcon(Context context, Cursor cursor, ViewHolder holder) {
+ Drawable icon = null;
+ byte[] data = null;
+
+ if (holder.iconBitmapIndex != -1) {
+ data = cursor.getBlob(holder.iconBitmapIndex);
+ }
+
+ if (data != null) {
+ final SoftReference<Drawable> reference = mCustomIcons.get(holder.id);
+ if (reference != null) {
+ icon = reference.get();
+ }
+
+ if (icon == null) {
+ final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+ icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, mContext));
+ mCustomIcons.put(holder.id, new SoftReference<Drawable>(icon));
+ }
+ } else if (holder.iconResourceIndex != -1 && holder.iconPackageIndex != -1) {
+ final String resource = cursor.getString(holder.iconResourceIndex);
+ icon = mIcons.get(resource);
+ if (icon == null) {
+ try {
+ final PackageManager packageManager = context.getPackageManager();
+ Resources resources = packageManager.getResourcesForApplication(
+ cursor.getString(holder.iconPackageIndex));
+ final int id = resources.getIdentifier(resource,
+ null, null);
+ icon = Utilities.createIconThumbnail(resources.getDrawable(id), mContext);
+ mIcons.put(resource, icon);
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+
+ return icon;
+ }
+
+ void cleanup() {
+ for (Drawable icon : mIcons.values()) {
+ icon.setCallback(null);
+ }
+ mIcons.clear();
+
+ for (SoftReference<Drawable> icon : mCustomIcons.values()) {
+ final Drawable drawable = icon.get();
+ if (drawable != null) {
+ drawable.setCallback(null);
+ }
+ }
+ mCustomIcons.clear();
+
+ try {
+ getCursor().close();
+ } finally {
+ mLauncher.stopManagingCursor(getCursor());
+ }
+ }
+
+ static class ViewHolder {
+ TextView name;
+ TextView description;
+ ImageView icon;
+
+ Intent intent;
+ long id;
+ boolean useBaseIntent;
+
+ int idIndex;
+ int nameIndex;
+ int descriptionIndex = -1;
+ int intentIndex = -1;
+ int iconBitmapIndex = -1;
+ int iconResourceIndex = -1;
+ int iconPackageIndex = -1;
+ }
+}
diff --git a/src/com/android/launcher/LiveFolderIcon.java b/src/com/android/launcher/LiveFolderIcon.java
new file mode 100644
index 000000000..33cb0b704
--- /dev/null
+++ b/src/com/android/launcher/LiveFolderIcon.java
@@ -0,0 +1,76 @@
+/*
+ * 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.android.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.graphics.drawable.Drawable;
+
+public class LiveFolderIcon extends FolderIcon {
+ public LiveFolderIcon(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LiveFolderIcon(Context context) {
+ super(context);
+ }
+
+ static LiveFolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
+ LiveFolderInfo folderInfo) {
+
+ LiveFolderIcon icon = (LiveFolderIcon)
+ LayoutInflater.from(launcher).inflate(resId, group, false);
+
+ final Resources resources = launcher.getResources();
+ Drawable d = folderInfo.icon;
+ if (d == null) {
+ resources.getDrawable(R.drawable.ic_launcher_folder);
+ d = Utilities.createIconThumbnail(d, launcher);
+ folderInfo.filtered = true;
+ }
+ icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
+ icon.setText(folderInfo.title);
+ icon.setTag(folderInfo);
+ icon.setOnClickListener(launcher);
+
+ return icon;
+ }
+
+ @Override
+ public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
+ return false;
+ }
+
+ @Override
+ public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
+ }
+
+ @Override
+ public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
+ }
+
+ @Override
+ public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
+ }
+
+ @Override
+ public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
+ }
+}
diff --git a/src/com/android/launcher/LiveFolderInfo.java b/src/com/android/launcher/LiveFolderInfo.java
new file mode 100644
index 000000000..2432cc365
--- /dev/null
+++ b/src/com/android/launcher/LiveFolderInfo.java
@@ -0,0 +1,75 @@
+/*
+ * 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.android.launcher;
+
+import android.content.ContentValues;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+
+class LiveFolderInfo extends FolderInfo {
+
+ /**
+ * The base intent, if it exists.
+ */
+ Intent baseIntent;
+
+ /**
+ * The live folder's content uri.
+ */
+ Uri uri;
+
+ /**
+ * The live folder's display type.
+ */
+ int displayMode;
+
+ /**
+ * The live folder icon.
+ */
+ Drawable icon;
+
+ /**
+ * When set to true, indicates that the icon has been resized.
+ */
+ boolean filtered;
+
+ /**
+ * Reference to the live folder icon as an application's resource.
+ */
+ Intent.ShortcutIconResource iconResource;
+
+ LiveFolderInfo() {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER;
+ }
+
+ @Override
+ void onAddToDatabase(ContentValues values) {
+ super.onAddToDatabase(values);
+ values.put(LauncherSettings.Favorites.TITLE, title.toString());
+ values.put(LauncherSettings.Favorites.URI, uri.toString());
+ if (baseIntent != null) {
+ values.put(LauncherSettings.Favorites.INTENT, baseIntent.toURI());
+ }
+ values.put(LauncherSettings.Favorites.ICON_TYPE, LauncherSettings.Favorites.ICON_TYPE_RESOURCE);
+ values.put(LauncherSettings.Favorites.DISPLAY_MODE, displayMode);
+ if (iconResource != null) {
+ values.put(LauncherSettings.Favorites.ICON_PACKAGE, iconResource.packageName);
+ values.put(LauncherSettings.Favorites.ICON_RESOURCE, iconResource.resourceName);
+ }
+ }
+}
diff --git a/src/com/android/launcher/Search.java b/src/com/android/launcher/Search.java
index 69e26ac59..b3305279f 100644
--- a/src/com/android/launcher/Search.java
+++ b/src/com/android/launcher/Search.java
@@ -16,13 +16,19 @@
package com.android.launcher;
+import java.util.List;
+
import android.app.ISearchManager;
import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -43,9 +49,9 @@ import android.view.View.OnKeyListener;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
-import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.Filter;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SimpleCursorAdapter;
@@ -59,7 +65,7 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
private final String TAG = "SearchGadget";
private AutoCompleteTextView mSearchText;
- private Button mGoButton;
+ private ImageButton mGoButton;
private OnLongClickListener mLongClickListener;
// Support for suggestions
@@ -69,12 +75,14 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
private Uri mSuggestionData = null;
private String mSuggestionQuery = null;
private int mItemSelected = -1;
+
+ private Rect mTempRect = new Rect();
/**
* Used to inflate the Workspace from XML.
*
* @param context The application's context.
- * @param attrs The attribtues set containing the Workspace's customization values.
+ * @param attrs The attributes set containing the Workspace's customization values.
*/
public Search(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -84,7 +92,9 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
* Implements OnClickListener (for button)
*/
public void onClick(View v) {
- query();
+ if (v == mGoButton) {
+ query();
+ }
}
private void query() {
@@ -92,7 +102,9 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
if (TextUtils.getTrimmedLength(mSearchText.getText()) == 0) {
return;
}
- sendLaunchIntent(Intent.ACTION_SEARCH, null, query, null, 0, null, mSearchable);
+ Bundle appData = new Bundle();
+ appData.putString(SearchManager.SOURCE, "launcher-widget");
+ sendLaunchIntent(Intent.ACTION_SEARCH, null, query, appData, 0, null, mSearchable);
}
/**
@@ -254,7 +266,7 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
mSearchText.setOnKeyListener(this);
mSearchText.addTextChangedListener(this);
- mGoButton = (Button) findViewById(R.id.go);
+ mGoButton = (ImageButton) findViewById(R.id.search_go_btn);
mGoButton.setOnClickListener(this);
mGoButton.setOnKeyListener(this);
@@ -296,8 +308,8 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
// attach the suggestions adapter
mSuggestionsAdapter = new SuggestionsAdapter(mContext,
- com.android.internal.R.layout.search_dropdown_item_1line, null,
- SuggestionsAdapter.ONE_LINE_FROM, SuggestionsAdapter.ONE_LINE_TO, mSearchable);
+ com.android.internal.R.layout.search_dropdown_item_2line, null,
+ SuggestionsAdapter.TWO_LINE_FROM, SuggestionsAdapter.TWO_LINE_TO, mSearchable);
mSearchText.setAdapter(mSuggestionsAdapter);
}
@@ -432,10 +444,14 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
/**
* This class provides the filtering-based interface to suggestions providers.
+ * It is hardwired in a couple of places to support GoogleSearch - for example, it supports
+ * two-line suggestions, but it does not support icons.
*/
private static class SuggestionsAdapter extends SimpleCursorAdapter {
- public final static String[] ONE_LINE_FROM = { SearchManager.SUGGEST_COLUMN_TEXT_1 };
- public final static int[] ONE_LINE_TO = { com.android.internal.R.id.text1 };
+ public final static String[] TWO_LINE_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2 };
+ public final static int[] TWO_LINE_TO = {com.android.internal.R.id.text1,
+ com.android.internal.R.id.text2};
private final String TAG = "SuggestionsAdapter";
diff --git a/src/com/android/launcher/UninstallShortcutReceiver.java b/src/com/android/launcher/UninstallShortcutReceiver.java
index 2d7909e67..e490f9c0f 100644
--- a/src/com/android/launcher/UninstallShortcutReceiver.java
+++ b/src/com/android/launcher/UninstallShortcutReceiver.java
@@ -21,11 +21,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.ContentResolver;
import android.database.Cursor;
+import android.net.Uri;
import java.net.URISyntaxException;
-import com.android.internal.provider.Settings;
-
public class UninstallShortcutReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent data) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
@@ -34,18 +33,23 @@ public class UninstallShortcutReceiver extends BroadcastReceiver {
if (intent != null && name != null) {
final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(Settings.Favorites.CONTENT_URI,
- new String[] { "_id", "intent" }, "title=?", new String[]{ name }, null);
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[] { LauncherSettings.Favorites.ID, LauncherSettings.Favorites.INTENT },
+ LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null);
+
+ final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
- final int intentIndex = c.getColumnIndexOrThrow(Settings.Favorites.INTENT);
- final int idIndex = c.getColumnIndexOrThrow(Settings.Favorites._ID);
+ boolean changed = false;
try {
while (c.moveToNext()) {
try {
if (intent.filterEquals(Intent.getIntent(c.getString(intentIndex)))) {
final long id = c.getLong(idIndex);
- cr.delete(Settings.Favorites.getContentUri(id, false), null, null);
+ final Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
+ cr.delete(uri, null, null);
+ changed = true;
if (!duplicate) {
break;
}
@@ -58,7 +62,7 @@ public class UninstallShortcutReceiver extends BroadcastReceiver {
c.close();
}
- cr.notifyChange(Settings.Favorites.CONTENT_URI, null);
+ if (changed) cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
}
}
}
diff --git a/src/com/android/launcher/UserFolder.java b/src/com/android/launcher/UserFolder.java
index dee44baa0..1044e969f 100644
--- a/src/com/android/launcher/UserFolder.java
+++ b/src/com/android/launcher/UserFolder.java
@@ -1,7 +1,6 @@
package com.android.launcher;
import android.content.Context;
-import com.android.internal.provider.Settings;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -31,8 +30,8 @@ public class UserFolder extends Folder implements DropTarget {
Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
final int itemType = item.itemType;
- return (itemType == Settings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == Settings.Favorites.ITEM_TYPE_SHORTCUT) && item.container != mInfo.id;
+ return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && item.container != mInfo.id;
}
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, Object dragInfo) {
@@ -52,13 +51,6 @@ public class UserFolder extends Folder implements DropTarget {
}
@Override
- public boolean onLongClick(View v) {
- mLauncher.closeFolder(this);
- mLauncher.showRenameDialog((UserFolderInfo) mInfo);
- return true;
- }
-
- @Override
public void onDropCompleted(View target, boolean success) {
if (success) {
//noinspection unchecked
@@ -68,10 +60,9 @@ public class UserFolder extends Folder implements DropTarget {
}
}
- void bind(UserFolderInfo info) {
- mInfo = info;
- setContentAdapter(new ApplicationsAdapter(mContext, info.contents));
- mCloseButton.setText(info.title);
+ void bind(FolderInfo info) {
+ super.bind(info);
+ setContentAdapter(new ApplicationsAdapter(mContext, ((UserFolderInfo) info).contents));
}
// When the folder opens, we need to refresh the GridView's selection by
diff --git a/src/com/android/launcher/UserFolderInfo.java b/src/com/android/launcher/UserFolderInfo.java
index 075b89a81..639894e59 100644
--- a/src/com/android/launcher/UserFolderInfo.java
+++ b/src/com/android/launcher/UserFolderInfo.java
@@ -17,7 +17,6 @@
package com.android.launcher;
import android.content.ContentValues;
-import com.android.internal.provider.Settings;
import java.util.ArrayList;
@@ -26,17 +25,12 @@ import java.util.ArrayList;
*/
class UserFolderInfo extends FolderInfo {
/**
- * The application name.
- */
- CharSequence title;
-
- /**
* The apps and shortcuts
*/
ArrayList<ApplicationInfo> contents = new ArrayList<ApplicationInfo>();
UserFolderInfo() {
- itemType = Settings.Favorites.ITEM_TYPE_USER_FOLDER;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
}
/**
@@ -60,6 +54,6 @@ class UserFolderInfo extends FolderInfo {
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
- values.put(Settings.Favorites.TITLE, title.toString());
+ values.put(LauncherSettings.Favorites.TITLE, title.toString());
}
}
diff --git a/src/com/android/launcher/Utilities.java b/src/com/android/launcher/Utilities.java
index 23738974c..cb8976ca9 100644
--- a/src/com/android/launcher/Utilities.java
+++ b/src/com/android/launcher/Utilities.java
@@ -18,7 +18,6 @@ package com.android.launcher;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Canvas;
@@ -97,30 +96,46 @@ final class Utilities {
painter.setIntrinsicHeight(height);
}
- if (width > 0 && height > 0 && (width < iconWidth || height < iconHeight)) {
- final float ratio = (float) iconWidth / iconHeight;
-
- if (iconWidth > iconHeight) {
- height = (int) (width / ratio);
- } else if (iconHeight > iconWidth) {
- width = (int) (height * ratio);
+ if (width > 0 && height > 0) {
+ if (width < iconWidth || height < iconHeight) {
+ final float ratio = (float) iconWidth / iconHeight;
+
+ if (iconWidth > iconHeight) {
+ height = (int) (width / ratio);
+ } else if (iconHeight > iconWidth) {
+ width = (int) (height * ratio);
+ }
+
+ final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
+ Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
+ final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
+ final Canvas canvas = sCanvas;
+ canvas.setBitmap(thumb);
+ // Copy the old bounds to restore them later
+ // If we were to do oldBounds = icon.getBounds(),
+ // the call to setBounds() that follows would
+ // change the same instance and we would lose the
+ // old bounds
+ sOldBounds.set(icon.getBounds());
+ final int x = (sIconWidth - width) / 2;
+ final int y = (sIconHeight - height) / 2;
+ icon.setBounds(x, y, x + width, y + height);
+ icon.draw(canvas);
+ icon.setBounds(sOldBounds);
+ icon = new FastBitmapDrawable(thumb);
+ } else if (iconWidth < width && iconHeight < height) {
+ final Bitmap.Config c = Bitmap.Config.ARGB_8888;
+ final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
+ final Canvas canvas = sCanvas;
+ canvas.setBitmap(thumb);
+ sOldBounds.set(icon.getBounds());
+ final int x = (width - iconWidth) / 2;
+ final int y = (height - iconHeight) / 2;
+ icon.setBounds(x, y, x + iconWidth, y + iconHeight);
+ icon.draw(canvas);
+ icon.setBounds(sOldBounds);
+ icon = new FastBitmapDrawable(thumb);
}
-
- final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
- Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
- final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
- final Canvas canvas = sCanvas;
- canvas.setBitmap(thumb);
- // Copy the old bounds to restore them later
- // If we were to do oldBounds = icon.getBounds(),
- // the call to setBounds() that follows would
- // change the same instance and we would lose the
- // old bounds
- sOldBounds.set(icon.getBounds());
- icon.setBounds((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);
- icon.draw(canvas);
- icon.setBounds(sOldBounds);
- icon = new BitmapDrawable(thumb);
}
return icon;
diff --git a/src/com/android/launcher/WallpaperChooser.java b/src/com/android/launcher/WallpaperChooser.java
index 268b571db..a4e583e30 100644
--- a/src/com/android/launcher/WallpaperChooser.java
+++ b/src/com/android/launcher/WallpaperChooser.java
@@ -102,6 +102,7 @@ public class WallpaperChooser extends Activity implements AdapterView.OnItemSele
mGallery = (Gallery) findViewById(R.id.gallery);
mGallery.setAdapter(new ImageAdapter(this));
mGallery.setOnItemSelectedListener(this);
+ mGallery.setCallbackDuringFling(false);
Button b = (Button) findViewById(R.id.set);
b.setOnClickListener(this);
diff --git a/src/com/android/launcher/Widget.java b/src/com/android/launcher/Widget.java
index b9d8ae676..881252222 100644
--- a/src/com/android/launcher/Widget.java
+++ b/src/com/android/launcher/Widget.java
@@ -18,7 +18,6 @@ package com.android.launcher;
import android.content.ContentValues;
import android.graphics.Bitmap;
-import com.android.internal.provider.Settings;
/**
* Represents one instance of a Launcher widget (clock, search, photo frame).
@@ -31,7 +30,7 @@ class Widget extends ItemInfo {
static Widget makeClock() {
Widget w = new Widget();
- w.itemType = Settings.Favorites.ITEM_TYPE_WIDGET_CLOCK;
+ w.itemType = LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK;
w.spanX = 2;
w.spanY = 2;
w.layoutResource = R.layout.widget_clock;
@@ -40,7 +39,7 @@ class Widget extends ItemInfo {
static Widget makePhotoFrame() {
Widget w = new Widget();
- w.itemType = Settings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME;
+ w.itemType = LauncherSettings.Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME;
w.spanX = 2;
w.spanY = 2;
w.layoutResource = R.layout.widget_photo_frame;
@@ -49,7 +48,7 @@ class Widget extends ItemInfo {
static Widget makeSearch() {
Widget w = new Widget();
- w.itemType = Settings.Favorites.ITEM_TYPE_WIDGET_SEARCH;
+ w.itemType = LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH;
w.spanX = 4;
w.spanY = 1;
w.layoutResource = R.layout.widget_search;
diff --git a/src/com/android/launcher/Workspace.java b/src/com/android/launcher/Workspace.java
index 73cff021e..0ca1b5af6 100644
--- a/src/com/android/launcher/Workspace.java
+++ b/src/com/android/launcher/Workspace.java
@@ -34,8 +34,6 @@ import android.widget.Scroller;
import android.os.Parcelable;
import android.os.Parcel;
-import com.android.internal.provider.Settings;
-
import java.util.ArrayList;
/**
@@ -249,7 +247,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
* @param currentScreen
*/
void setCurrentScreen(int currentScreen) {
- mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount()));
+ mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
scrollTo(mCurrentScreen * getWidth(), 0);
invalidate();
}
@@ -426,7 +424,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
mScrollY = mScroller.getCurrY();
postInvalidate();
} else if (mNextScreen != INVALID_SCREEN) {
- mCurrentScreen = mNextScreen;
+ mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
Launcher.setScreen(mCurrentScreen);
mNextScreen = INVALID_SCREEN;
clearChildrenCache();
@@ -784,6 +782,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
void snapToScreen(int whichScreen) {
enableChildrenCache();
+ whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
boolean changingScreens = whichScreen != mCurrentScreen;
mNextScreen = whichScreen;
@@ -861,7 +860,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
final ItemInfo info = (ItemInfo)cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
LauncherModel.moveItemInDatabase(mLauncher, info,
- Settings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
}
}
}
@@ -885,8 +884,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
View view;
switch (info.itemType) {
- case Settings.Favorites.ITEM_TYPE_APPLICATION:
- case Settings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (info.container == NO_ID) {
// Came from all apps -- make a copy
info = new ApplicationInfo((ApplicationInfo) info);
@@ -894,7 +893,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
view = mLauncher.createShortcut(R.layout.application, cellLayout,
(ApplicationInfo) info);
break;
- case Settings.Favorites.ITEM_TYPE_USER_FOLDER:
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
(ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info));
break;
@@ -910,7 +909,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
final LauncherModel model = Launcher.getModel();
model.addDesktopItem(info);
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
- Settings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
}
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,