diff options
25 files changed, 1471 insertions, 7 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index adbd457..b22c96b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1200,7 +1200,7 @@ <activity android:name="ActivityPicker" android:label="@string/activity_picker_label" - android:theme="@*android:style/Theme.Dialog.Alert" + android:theme="@*android:style/Theme.Holo.Dialog.Alert" android:finishOnCloseSystemDialogs="true"> <intent-filter> <action android:name="android.intent.action.PICK_ACTIVITY" /> @@ -1477,6 +1477,10 @@ <activity android:name=".profiles.NFCProfileSelect" /> + <activity android:name=".cyanogenmod.LockscreenTargets" /> + + <activity android:name=".cyanogenmod.LockscreenInterface" /> + <activity android:name=".cyanogenmod.PowerMenu" /> <activity android:name=".profiles.NFCProfile" diff --git a/res/drawable-hdpi/ic_empty.png b/res/drawable-hdpi/ic_empty.png Binary files differnew file mode 100644 index 0000000..a45c6cf --- /dev/null +++ b/res/drawable-hdpi/ic_empty.png diff --git a/res/drawable-hdpi/ic_menu_save.png b/res/drawable-hdpi/ic_menu_save.png Binary files differnew file mode 100644 index 0000000..2b29557 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_save.png diff --git a/res/drawable-hdpi/ic_settings_lockscreen.png b/res/drawable-hdpi/ic_settings_lockscreen.png Binary files differnew file mode 100644 index 0000000..a08d513 --- /dev/null +++ b/res/drawable-hdpi/ic_settings_lockscreen.png diff --git a/res/drawable-mdpi/ic_empty.png b/res/drawable-mdpi/ic_empty.png Binary files differnew file mode 100644 index 0000000..ede2c83 --- /dev/null +++ b/res/drawable-mdpi/ic_empty.png diff --git a/res/drawable-mdpi/ic_menu_save.png b/res/drawable-mdpi/ic_menu_save.png Binary files differnew file mode 100644 index 0000000..283be30 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_save.png diff --git a/res/drawable-mdpi/ic_settings_lockscreen.png b/res/drawable-mdpi/ic_settings_lockscreen.png Binary files differnew file mode 100644 index 0000000..ac18347 --- /dev/null +++ b/res/drawable-mdpi/ic_settings_lockscreen.png diff --git a/res/drawable-xhdpi/ic_empty.png b/res/drawable-xhdpi/ic_empty.png Binary files differnew file mode 100644 index 0000000..5742d13 --- /dev/null +++ b/res/drawable-xhdpi/ic_empty.png diff --git a/res/drawable-xhdpi/ic_menu_save.png b/res/drawable-xhdpi/ic_menu_save.png Binary files differnew file mode 100644 index 0000000..c403206 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_save.png diff --git a/res/drawable-xhdpi/ic_settings_lockscreen.png b/res/drawable-xhdpi/ic_settings_lockscreen.png Binary files differnew file mode 100644 index 0000000..f669da1 --- /dev/null +++ b/res/drawable-xhdpi/ic_settings_lockscreen.png diff --git a/res/drawable/activities_icon.png b/res/drawable/activities_icon.png Binary files differnew file mode 100644 index 0000000..abd62e2 --- /dev/null +++ b/res/drawable/activities_icon.png diff --git a/res/layout-land/lockscreen_targets.xml b/res/layout-land/lockscreen_targets.xml new file mode 100644 index 0000000..22f0d4a --- /dev/null +++ b/res/layout-land/lockscreen_targets.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@android:color/holo_blue_light" + android:layout_marginRight="8dip" + android:layout_marginLeft="8dip" + android:padding="4dip" + android:gravity="center_horizontal" + android:textColor="#FFFFFF" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="@string/lockscreen_target_info" /> + + <View + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <com.android.internal.widget.multiwaveview.GlowPadView + android:id="@+id/lock_target" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="horizontal" + android:gravity="@*android:integer/kg_selector_gravity" + android:contentDescription="@*android:string/keyguard_accessibility_slide_area" + prvandroid:targetDrawables="@*android:array/lockscreen_targets_unlock_only" + prvandroid:targetDescriptions="@*android:array/lockscreen_target_descriptions_unlock_only" + prvandroid:directionDescriptions="@*android:array/lockscreen_direction_descriptions" + prvandroid:handleDrawable="@*android:drawable/ic_lockscreen_handle" + prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring" + prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius" + prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius" + prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin" + prvandroid:firstItemOffset="@*android:integer/kg_glowpad_rotation_offset" + prvandroid:magneticTargets="false" + prvandroid:feedbackCount="1" + prvandroid:vibrationDuration="20" + prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius" + prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot" + prvandroid:allowScaling="true" /> + +</LinearLayout> diff --git a/res/layout-sw600dp/lockscreen_targets.xml b/res/layout-sw600dp/lockscreen_targets.xml new file mode 100644 index 0000000..22f0d4a --- /dev/null +++ b/res/layout-sw600dp/lockscreen_targets.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@android:color/holo_blue_light" + android:layout_marginRight="8dip" + android:layout_marginLeft="8dip" + android:padding="4dip" + android:gravity="center_horizontal" + android:textColor="#FFFFFF" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="@string/lockscreen_target_info" /> + + <View + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <com.android.internal.widget.multiwaveview.GlowPadView + android:id="@+id/lock_target" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="horizontal" + android:gravity="@*android:integer/kg_selector_gravity" + android:contentDescription="@*android:string/keyguard_accessibility_slide_area" + prvandroid:targetDrawables="@*android:array/lockscreen_targets_unlock_only" + prvandroid:targetDescriptions="@*android:array/lockscreen_target_descriptions_unlock_only" + prvandroid:directionDescriptions="@*android:array/lockscreen_direction_descriptions" + prvandroid:handleDrawable="@*android:drawable/ic_lockscreen_handle" + prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring" + prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius" + prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius" + prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin" + prvandroid:firstItemOffset="@*android:integer/kg_glowpad_rotation_offset" + prvandroid:magneticTargets="false" + prvandroid:feedbackCount="1" + prvandroid:vibrationDuration="20" + prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius" + prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot" + prvandroid:allowScaling="true" /> + +</LinearLayout> diff --git a/res/layout/lockscreen_shortcut_dialog.xml b/res/layout/lockscreen_shortcut_dialog.xml new file mode 100644 index 0000000..638af0f --- /dev/null +++ b/res/layout/lockscreen_shortcut_dialog.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:minHeight="?android:attr/listPreferredItemHeight" + android:layout_height="wrap_content" + android:paddingBottom="5dp" + android:paddingLeft="8dp" + android:gravity="center_vertical" + android:orientation="horizontal"> + <ImageButton + android:padding="5dp" + android:layout_width="@android:dimen/app_icon_size" + style="?android:attr/borderlessButtonStyle" + android:id="@+id/icon" + android:layout_height="@android:dimen/app_icon_size" /> + <View + android:layout_width="2dp" + android:layout_height="match_parent" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp" + android:layout_marginRight="5dp" + android:layout_marginLeft="5dp" + android:background="@android:drawable/divider_horizontal_dark" /> + <Button + android:layout_width="match_parent" + style="?android:attr/borderlessButtonStyle" + android:gravity="left|center_vertical" + android:paddingLeft="5dp" + android:layout_height="wrap_content" + android:id="@+id/label" /> +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/lockscreen_targets.xml b/res/layout/lockscreen_targets.xml new file mode 100644 index 0000000..cff327c --- /dev/null +++ b/res/layout/lockscreen_targets.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@android:color/holo_blue_light" + android:layout_marginRight="8dip" + android:layout_marginLeft="8dip" + android:padding="4dip" + android:gravity="center_horizontal" + android:textColor="#FFFFFF" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="@string/lockscreen_target_info" /> + + <View + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="0.4" /> + + <com.android.internal.widget.multiwaveview.GlowPadView + android:id="@+id/lock_target" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="0.6" + android:orientation="horizontal" + android:gravity="top" + android:contentDescription="@*android:string/keyguard_accessibility_slide_area" + prvandroid:targetDrawables="@*android:array/lockscreen_targets_unlock_only" + prvandroid:targetDescriptions="@*android:array/lockscreen_target_descriptions_unlock_only" + prvandroid:directionDescriptions="@*android:array/lockscreen_direction_descriptions" + prvandroid:handleDrawable="@*android:drawable/ic_lockscreen_handle" + prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring" + prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius" + prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius" + prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin" + prvandroid:firstItemOffset="@*android:integer/kg_glowpad_rotation_offset" + prvandroid:magneticTargets="false" + prvandroid:feedbackCount="1" + prvandroid:vibrationDuration="20" + prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius" + prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot" + prvandroid:allowScaling="true" /> + +</LinearLayout> diff --git a/res/layout/pick_item.xml b/res/layout/pick_item.xml index d85edc4..e937d7b 100755 --- a/res/layout/pick_item.xml +++ b/res/layout/pick_item.xml @@ -17,9 +17,9 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" - android:textAppearance="?android:attr/textAppearanceMedium" + android:minHeight="?android:attr/listPreferredItemHeight" + android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" - android:drawablePadding="8dip" - android:paddingStart="11dip" - android:paddingEnd="11dip" /> + android:drawablePadding="14dip" + android:paddingLeft="15dip" + android:paddingRight="15dip" /> diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 2935cbf..bc222ad 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -847,6 +847,56 @@ <item>2</item> </string-array> + <string-array name="lockscreen_icon_picker_labels" translatable="false"> + <item>@string/icon_picker_alarm</item> + <item>@string/icon_picker_browser</item> + <item>@string/icon_picker_calendar</item> + <item>@string/icon_picker_camera</item> + <item>@string/icon_picker_chrome</item> + <item>@string/icon_picker_email</item> + <item>@string/icon_picker_email2</item> + <item>@string/icon_picker_facebook</item> + <item>@string/icon_picker_gallery</item> + <item>@string/icon_picker_google_small</item> + <item>@string/icon_picker_googleplus</item> + <item>@string/icon_picker_googletalk</item> + <item>@string/icon_picker_maps</item> + <item>@string/icon_picker_sms</item> + <item>@string/icon_picker_movie</item> + <item>@string/icon_picker_music</item> + <item>@string/icon_picker_nav_normal</item> + <item>@string/icon_picker_phone</item> + <item>@string/icon_picker_podcast</item> + <item>@string/icon_picker_rss</item> + <item>@string/icon_picker_search</item> + <item>@string/icon_picker_twitter</item> + </string-array> + + <string-array name="lockscreen_icon_picker_icons" translatable="false"> + <item>@*android:drawable/ic_lockscreen_alarm_normal</item> + <item>@*android:drawable/ic_lockscreen_browser_normal</item> + <item>@*android:drawable/ic_lockscreen_calendar_normal</item> + <item>@*android:drawable/ic_lockscreen_camera_normal</item> + <item>@*android:drawable/ic_lockscreen_chrome_normal</item> + <item>@*android:drawable/ic_lockscreen_email_normal</item> + <item>@*android:drawable/ic_lockscreen_email2_normal</item> + <item>@*android:drawable/ic_lockscreen_facebook_normal</item> + <item>@*android:drawable/ic_lockscreen_gallery_normal</item> + <item>@*android:drawable/ic_lockscreen_google_small_normal</item> + <item>@*android:drawable/ic_lockscreen_gplus_normal</item> + <item>@*android:drawable/ic_lockscreen_gtalk_normal</item> + <item>@*android:drawable/ic_lockscreen_maps_normal</item> + <item>@*android:drawable/ic_lockscreen_sms_normal</item> + <item>@*android:drawable/ic_lockscreen_movie_normal</item> + <item>@*android:drawable/ic_lockscreen_music_normal</item> + <item>@*android:drawable/ic_lockscreen_nav_normal</item> + <item>@*android:drawable/ic_lockscreen_phone_normal</item> + <item>@*android:drawable/ic_lockscreen_podcast_normal</item> + <item>@*android:drawable/ic_lockscreen_rss_normal</item> + <item>@*android:drawable/ic_lockscreen_google_normal</item> + <item>@*android:drawable/ic_lockscreen_twitter_normal</item> + </string-array> + <!-- Profile mode options. --> <string-array name="profile_entries"> <item>On</item> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index cbc9b6d..2f0f859 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -31,7 +31,7 @@ <dimen name="data_usage_chart_height">252dip</dimen> <dimen name="data_usage_chart_optimalWidth">440dip</dimen> - + <dimen name="shortcut_picker_left_padding">70dip</dimen> <dimen name="volume_seekbar_side_margin">8dip</dimen> <dimen name="crypt_clock_size">100sp</dimen> diff --git a/res/values/strings.xml b/res/values/strings.xml index 24af239..0179aaf 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4496,6 +4496,18 @@ <string name="lock_screen_title">Lock screen</string> + <!-- Lock Screen Shortcuts --> + <string name="lockscreen_target_info">Drag the slider to targets to assign shortcuts</string> + <string name="lockscreen_target_title">Slider shortcuts</string> + <string name="lockscreen_target_summary">View or change custom lock screen shortcuts</string> + <string name="lockscreen_target_reset">Lock screen shortcuts reset to default</string> + <string name="lockscreen_target_save">Lock screen shortcuts saved</string> + <string name="lockscreen_target_reset_title">Reset</string> + <string name="lockscreen_target_reset_message">Delete all user created lock screen shortcuts and restore to default?</string> + <string name="lockscreen_target_empty">Empty</string> + <string name="lockscreen_target_edit_title">Edit shortcut and icon</string> + <string name="lockscreen_target_edit_msg">Select or change the desired application or activity and the associated icon</string> + <!-- Profiles settings --> <string name="profiles_settings_title">Profiles</string> <string name="profiles_general_title">General</string> @@ -4684,6 +4696,40 @@ <string name="display_rotation_180_title">180 degrees</string> <string name="display_rotation_270_title">270 degrees</string> + <!-- Lock screen shortcuts --> + <string name="picker_activities">Activities</string> + <string name="select_custom_app_title">Select custom application</string> + <string name="select_custom_activity_title">Select custom activity</string> + <string name="icon_picker_choose_icon_title">Choose icon</string> + <string name="icon_picker_alarm">Alarm</string> + <string name="icon_picker_browser">Browser</string> + <string name="icon_picker_calendar">Calendar</string> + <string name="icon_picker_camera">Camera</string> + <string name="icon_picker_chrome">Chrome</string> + <string name="icon_picker_email">Email</string> + <string name="icon_picker_email2">Email Holo</string> + <string name="icon_picker_facebook">Facebook</string> + <string name="icon_picker_gallery">Gallery</string> + <string name="icon_picker_google_small">Google (small)</string> + <string name="icon_picker_googleplus">Google Plus</string> + <string name="icon_picker_googletalk">Google Talk</string> + <string name="icon_picker_maps">Maps</string> + <string name="icon_picker_movie">Movie</string> + <string name="icon_picker_music">Music</string> + <string name="icon_picker_nav_normal">Navigation</string> + <string name="icon_picker_phone">Phone</string> + <string name="icon_picker_podcast">Podcast</string> + <string name="icon_picker_rss">Rss</string> + <string name="icon_picker_search">Search</string> + <string name="icon_picker_sms">Messaging</string> + <string name="icon_picker_twitter">Twitter</string> + + <!-- String for IconPicker --> + <string name="icon_picker_title">Choose icon source</string> + <string name="icon_picker_system_icons_title">System icons</string> + <string name="icon_picker_gallery_title">Gallery</string> + <string name="icon_picker_pack_title">Icon pack</string> + <string name="increasing_ring_title">Ascending ringtone</string> <!-- Sound settings screen, the caption of the checkbox for making incoming calls increase in volume --> <string name="checkbox_increasing_ring">Enable</string> diff --git a/res/xml/lockscreen_interface_settings.xml b/res/xml/lockscreen_interface_settings.xml new file mode 100644 index 0000000..1142264 --- /dev/null +++ b/res/xml/lockscreen_interface_settings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 The CyanogenMod 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. +--> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" + android:title="@string/themes_settings_title" > + + <Preference + android:fragment="com.android.settings.cyanogenmod.LockscreenTargets" + android:key="lockscreen_targets" + android:summary="@string/lockscreen_target_summary" + android:title="@string/lockscreen_target_title" /> + +</PreferenceScreen> diff --git a/res/xml/settings_headers.xml b/res/xml/settings_headers.xml index 05cc2be..5f1fd54 100644 --- a/res/xml/settings_headers.xml +++ b/res/xml/settings_headers.xml @@ -67,6 +67,13 @@ android:title="@string/launcher_settings_title" android:icon="@drawable/ic_settings_cmlauncher" /> + <!-- Lock screen --> + <header + android:id="@+id/lock_screen_settings" + android:fragment="com.android.settings.cyanogenmod.LockscreenInterface" + android:title="@string/lock_screen_title" + android:icon="@drawable/ic_settings_lockscreen" /> + <!-- Themes --> <header android:id="@+id/themes_settings" diff --git a/src/com/android/settings/cyanogenmod/IconPicker.java b/src/com/android/settings/cyanogenmod/IconPicker.java new file mode 100644 index 0000000..386468a --- /dev/null +++ b/src/com/android/settings/cyanogenmod/IconPicker.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2012 The CyanogenMod 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.settings.cyanogenmod; + +import java.io.File; +import java.util.ArrayList; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.Fragment; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.provider.MediaStore; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import com.android.settings.R; + +public class IconPicker { + + private Activity mParent; + private Resources mResources; + private OnIconPickListener mIconListener; + private static final String ICON_ACTION = "com.cyanogenmod.ACTION_PICK_ICON"; + public static final String RESOURCE_NAME = "resource_name"; + public static final String PACKAGE_NAME = "package_name"; + public static final int REQUEST_PICK_SYSTEM = 0; + public static final int REQUEST_PICK_GALLERY = 1; + public static final int REQUEST_PICK_ICON_PACK = 2; + + public interface OnIconPickListener { + void iconPicked(int requestCode, int resultCode, Intent in); + } + + public IconPicker(Activity parent, OnIconPickListener listener) { + mParent = parent; + mResources = parent.getResources(); + mIconListener = listener; + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mIconListener.iconPicked(requestCode, resultCode, data); + } + + public void pickIcon(final int fragmentId, final File image) { + Intent iconPack = new Intent(ICON_ACTION); + ArrayList<String> items = new ArrayList<String>(); + items.add(mResources.getString(R.string.icon_picker_system_icons_title)); + items.add(mResources.getString(R.string.icon_picker_gallery_title)); + ComponentName aInfo = iconPack.resolveActivity(mParent.getPackageManager()); + if (aInfo != null) { + items.add(mResources.getString(R.string.icon_picker_pack_title)); + } + new AlertDialog.Builder(mParent) + .setTitle(R.string.icon_picker_title) + .setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + showChosen(item, image, fragmentId); + } + }).show(); + } + + private void startFragmentOrActivityForResult(Intent pickIntent, int requestCode, int fragmentId) { + if (fragmentId == 0) { + mParent.startActivityForResult(pickIntent, requestCode); + } else { + Fragment cFrag = mParent.getFragmentManager().findFragmentById(fragmentId); + if (cFrag != null) { + mParent.startActivityFromFragment(cFrag, pickIntent, requestCode); + } + } + } + + private void showChosen(final int type, File image, int fragmentId) { + if (type == REQUEST_PICK_SYSTEM) { + ListView listie = new ListView(mParent); + listie.setAdapter(new IconAdapter()); + final Dialog dialog = new Dialog(mParent); + dialog.setTitle(R.string.icon_picker_choose_icon_title); + dialog.setContentView(listie); + listie.setOnItemClickListener(new OnItemClickListener(){ + @Override + public void onItemClick(AdapterView<?> parent, View view, + int position, long id) { + Intent in = new Intent(); + in.putExtra("resource_name", ((IconAdapter) parent.getAdapter()).getItemReference(position)); + mIconListener.iconPicked(type, Activity.RESULT_OK, in); + dialog.dismiss(); + } + }); + dialog.show(); + } else if (type == REQUEST_PICK_GALLERY) { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); + intent.setType("image/*"); + intent.putExtra("crop", "true"); + intent.putExtra("scale", true); + intent.putExtra("scaleUpIfNeeded", false); + intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString()); + intent.putExtra("aspectX", 1); + intent.putExtra("aspectY", 1); + intent.putExtra("outputX", 162); + intent.putExtra("outputY", 162); + try { + intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(image)); + intent.putExtra("return-data", false); + startFragmentOrActivityForResult(intent, type, fragmentId); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + } + } else if (type == REQUEST_PICK_ICON_PACK) { + Intent iconPack = new Intent(ICON_ACTION); + startFragmentOrActivityForResult(iconPack, type, fragmentId); + } + } + + class IconAdapter extends BaseAdapter { + + String[] labels; + TypedArray icons; + + public IconAdapter() { + labels = mResources.getStringArray(R.array.lockscreen_icon_picker_labels); + icons = mResources.obtainTypedArray(R.array.lockscreen_icon_picker_icons); + } + + @Override + public int getCount() { + return labels.length; + } + + @Override + public Object getItem(int position) { + return icons.getDrawable(position); + } + + public String getItemReference(int position) { + String name = icons.getString(position); + int separatorIndex = name.lastIndexOf(File.separator); + int periodIndex = name.lastIndexOf('.'); + return name.substring(separatorIndex + 1, periodIndex); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View iView = convertView; + if (convertView == null) { + iView = View.inflate(mParent, android.R.layout.simple_list_item_1, null); + } + TextView tt = (TextView) iView.findViewById(android.R.id.text1); + tt.setText(labels[position]); + Drawable ic = ((Drawable) getItem(position)).mutate(); + int bound = mParent.getResources().getDimensionPixelSize(R.dimen.shortcut_picker_left_padding); + ic.setBounds(0, 0, bound, bound); + tt.setCompoundDrawables(ic, null, null, null); + return iView; + } + + } + + class IconItem { + String label; + int id; + IconItem(String l, int i) { + label = l; + id = i; + } + } + +}
\ No newline at end of file diff --git a/src/com/android/settings/cyanogenmod/LockscreenInterface.java b/src/com/android/settings/cyanogenmod/LockscreenInterface.java new file mode 100644 index 0000000..1a13e04 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/LockscreenInterface.java @@ -0,0 +1,53 @@ +/* + * + * 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.settings.cyanogenmod; + +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +public class LockscreenInterface extends SettingsPreferenceFragment { + private static final String TAG = "LockscreenInterface"; + + public boolean hasButtons() { + return !getResources().getBoolean(com.android.internal.R.bool.config_showNavigationBar); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.lockscreen_interface_settings); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { + return super.onPreferenceTreeClick(preferenceScreen, preference); + } +} diff --git a/src/com/android/settings/cyanogenmod/LockscreenTargets.java b/src/com/android/settings/cyanogenmod/LockscreenTargets.java new file mode 100644 index 0000000..b788030 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/LockscreenTargets.java @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2012 The CyanogenMod 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.settings.cyanogenmod; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.Intent.ShortcutIconResource; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.InsetDrawable; +import android.graphics.drawable.LayerDrawable; +import android.graphics.drawable.StateListDrawable; +import android.os.Bundle; +import android.provider.Settings; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.internal.widget.multiwaveview.GlowPadView; +import com.android.internal.widget.multiwaveview.TargetDrawable; +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.cyanogenmod.IconPicker.OnIconPickListener; + +public class LockscreenTargets extends Fragment implements ShortcutPickHelper.OnPickListener, + GlowPadView.OnTriggerListener, OnIconPickListener { + + private GlowPadView mWaveView; + private ImageButton mDialogIcon; + private Button mDialogLabel; + private ShortcutPickHelper mPicker; + private IconPicker mIconPicker; + private ArrayList<TargetInfo> mTargetStore = new ArrayList<TargetInfo>(); + private int mTargetOffset; + private int mTargetInset; + private boolean mIsLandscape; + private boolean mIsScreenLarge; + private ViewGroup mContainer; + private Activity mActivity; + private Resources mResources; + private File mImageTmp; + private int mTargetIndex = 0; + private static final int MENU_RESET = Menu.FIRST; + private static final int MENU_SAVE = Menu.FIRST + 1; + private static String EMPTY_LABEL; + + class TargetInfo { + String uri, pkgName; + StateListDrawable icon; + Drawable defaultIcon; + String iconType; + String iconSource; + TargetInfo(StateListDrawable target) { + icon = target; + } + TargetInfo(String in, StateListDrawable target, String iType, String iSource, Drawable dI) { + uri = in; + icon = target; + defaultIcon = dI; + iconType = iType; + iconSource = iSource; + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mContainer = container; + setHasOptionsMenu(true); + mActivity = getActivity(); + mIsScreenLarge = !Utils.isPhone(mActivity); + mResources = getResources(); + mIsLandscape = mResources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; + mTargetOffset = mIsLandscape && !mIsScreenLarge ? 2 : 0; + mTargetInset = mResources.getDimensionPixelSize(com.android.internal.R.dimen.lockscreen_target_inset); + mIconPicker = new IconPicker(mActivity, this); + mPicker = new ShortcutPickHelper(mActivity, this); + mImageTmp = new File(mActivity.getCacheDir() + "/target.tmp"); + EMPTY_LABEL = mActivity.getResources().getString(R.string.lockscreen_target_empty); + return inflater.inflate(R.layout.lockscreen_targets, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mWaveView = ((GlowPadView) mActivity.findViewById(R.id.lock_target)); + mWaveView.setOnTriggerListener(this); + initializeView(Settings.System.getString(mActivity.getContentResolver(), Settings.System.LOCKSCREEN_TARGETS)); + } + + /** + * Create a layered drawable + * @param back - Background image to use when target is active + * @param front - Front image to use for target + * @param inset - Target inset padding + * @param frontBlank - Whether the front image for active target should be blank + * @return StateListDrawable + */ + private StateListDrawable getLayeredDrawable(Drawable back, Drawable front, int inset, boolean frontBlank) { + front.mutate(); + back.mutate(); + InsetDrawable[] inactivelayer = new InsetDrawable[2]; + InsetDrawable[] activelayer = new InsetDrawable[2]; + Drawable activeFront = frontBlank ? mResources.getDrawable(android.R.color.transparent) : front; + Drawable inactiveBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_lock_pressed); + inactivelayer[0] = new InsetDrawable(inactiveBack, 0, 0, 0, 0); + inactivelayer[1] = new InsetDrawable(front, inset, inset, inset, inset); + activelayer[0] = new InsetDrawable(back, 0, 0, 0, 0); + activelayer[1] = new InsetDrawable(activeFront, inset, inset, inset, inset); + StateListDrawable states = new StateListDrawable(); + LayerDrawable inactiveLayerDrawable = new LayerDrawable(inactivelayer); + inactiveLayerDrawable.setId(0, 0); + inactiveLayerDrawable.setId(1, 1); + LayerDrawable activeLayerDrawable = new LayerDrawable(activelayer); + activeLayerDrawable.setId(0, 0); + activeLayerDrawable.setId(1, 1); + states.addState(TargetDrawable.STATE_INACTIVE, inactiveLayerDrawable); + states.addState(TargetDrawable.STATE_ACTIVE, activeLayerDrawable); + states.addState(TargetDrawable.STATE_FOCUSED, activeLayerDrawable); + return states; + } + + private void initializeView(String input) { + if (input == null) { + input = GlowPadView.EMPTY_TARGET; + } + mTargetStore.clear(); + final int maxTargets = mIsScreenLarge ? GlowPadView.MAX_TABLET_TARGETS : GlowPadView.MAX_PHONE_TARGETS; + final PackageManager packMan = mActivity.getPackageManager(); + final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated); + final String[] targetStore = input.split("\\|"); + //Shift by 2 targets for phones in landscape + if (mIsLandscape && !mIsScreenLarge) { + mTargetStore.add(new TargetInfo(null)); + mTargetStore.add(new TargetInfo(null)); + } + //Add the unlock icon + Drawable unlockFront = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_unlock_normal); + Drawable unlockBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_unlock_activated); + mTargetStore.add(new TargetInfo(getLayeredDrawable(unlockBack, unlockFront, 0, true))); + for (int cc = 0; cc < 8 - mTargetOffset - 1; cc++) { + String uri = GlowPadView.EMPTY_TARGET; + Drawable front = null; + Drawable back = activeBack; + boolean frontBlank = false; + String iconType = null; + String iconSource = null; + int tmpInset = mTargetInset; + if (cc < targetStore.length && cc < maxTargets) { + uri = targetStore[cc]; + if (!uri.equals(GlowPadView.EMPTY_TARGET)) { + try { + Intent in = Intent.parseUri(uri, 0); + if (in.hasExtra(GlowPadView.ICON_FILE)) { + String rSource = in.getStringExtra(GlowPadView.ICON_FILE); + File fPath = new File(rSource); + if (fPath != null) { + if (fPath.exists()) { + front = new BitmapDrawable(getResources(), BitmapFactory.decodeFile(rSource)); + } + } + } else if (in.hasExtra(GlowPadView.ICON_RESOURCE)) { + String rSource = in.getStringExtra(GlowPadView.ICON_RESOURCE); + String rPackage = in.getStringExtra(GlowPadView.ICON_PACKAGE); + if (rSource != null) { + if (rPackage != null) { + try { + Context rContext = mActivity.createPackageContext(rPackage, 0); + int id = rContext.getResources().getIdentifier(rSource, "drawable", rPackage); + front = rContext.getResources().getDrawable(id); + id = rContext.getResources().getIdentifier(rSource.replaceAll("_normal", "_activated"), + "drawable", rPackage); + back = rContext.getResources().getDrawable(id); + tmpInset = 0; + frontBlank = true; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } catch (NotFoundException e) { + e.printStackTrace(); + } + } else { + front = mResources.getDrawable(mResources.getIdentifier(rSource, "drawable", "android")); + back = mResources.getDrawable(mResources.getIdentifier( + rSource.replaceAll("_normal", "_activated"), "drawable", "android")); + tmpInset = 0; + frontBlank = true; + } + } + } + if (front == null) { + ActivityInfo aInfo = in.resolveActivityInfo(packMan, PackageManager.GET_ACTIVITIES); + if (aInfo != null) { + front = aInfo.loadIcon(packMan); + } else { + front = mResources.getDrawable(android.R.drawable.sym_def_app_icon).mutate(); + } + } + } catch (Exception e) { + } + } + } else if (cc >= maxTargets) { + mTargetStore.add(new TargetInfo(null)); + continue; + } + if (back == null || front == null) { + Drawable emptyIcon = mResources.getDrawable(R.drawable.ic_empty).mutate(); + front = emptyIcon; + } + mTargetStore.add(new TargetInfo(uri, getLayeredDrawable(back,front, tmpInset, frontBlank), iconType, + iconSource, front.getConstantState().newDrawable().mutate())); + } + ArrayList<TargetDrawable> tDraw = new ArrayList<TargetDrawable>(); + for (TargetInfo i : mTargetStore) { + if (i != null) { + tDraw.add(new TargetDrawable(mResources, i.icon)); + } else { + tDraw.add(new TargetDrawable(mResources, null)); + } + } + mWaveView.setTargetResources(tDraw); + } + + @Override + public void onResume() { + super.onResume(); + // If running on a phone, remove padding around container + if (!mIsScreenLarge) { + mContainer.setPadding(0, 0, 0, 0); + } + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add(0, MENU_RESET, 0, R.string.profile_reset_title) + .setIcon(R.drawable.ic_settings_backup) // use the backup icon + .setAlphabeticShortcut('r') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(0, MENU_SAVE, 0, R.string.wifi_save) + .setIcon(R.drawable.ic_menu_save) + .setAlphabeticShortcut('s') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_RESET: + resetAll(); + return true; + case MENU_SAVE: + saveAll(); + Toast.makeText(mActivity, R.string.lockscreen_target_save, Toast.LENGTH_LONG).show(); + return true; + default: + return false; + } + } + + /** + * Resets the target layout to stock + */ + private void resetAll() { + new AlertDialog.Builder(mActivity) + .setTitle(R.string.lockscreen_target_reset_title) + .setIconAttribute(android.R.attr.alertDialogIcon) + .setMessage(R.string.lockscreen_target_reset_message) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + initializeView(GlowPadView.EMPTY_TARGET); + saveAll(); + Toast.makeText(mActivity, R.string.lockscreen_target_reset, Toast.LENGTH_LONG).show(); + } + }).setNegativeButton(R.string.cancel, null) + .create().show(); + } + + /** + * Save targets to settings provider + */ + private void saveAll() { + StringBuilder targetLayout = new StringBuilder(); + ArrayList<String> existingImages = new ArrayList<String>(); + final int maxTargets = mIsScreenLarge ? GlowPadView.MAX_TABLET_TARGETS : GlowPadView.MAX_PHONE_TARGETS; + for (int i = mTargetOffset + 1; i <= mTargetOffset + maxTargets; i++) { + String uri = mTargetStore.get(i).uri; + String type = mTargetStore.get(i).iconType; + String source = mTargetStore.get(i).iconSource; + existingImages.add(source); + if (!uri.equals(GlowPadView.EMPTY_TARGET) && type != null) { + try { + Intent in = Intent.parseUri(uri, 0); + in.putExtra(type, source); + String pkgName = mTargetStore.get(i).pkgName; + if (pkgName != null) { + in.putExtra(GlowPadView.ICON_PACKAGE, mTargetStore.get(i).pkgName); + } else { + in.removeExtra(GlowPadView.ICON_PACKAGE); + } + uri = in.toUri(0); + } catch (URISyntaxException e) { + } + } + targetLayout.append(uri); + targetLayout.append("|"); + } + targetLayout.deleteCharAt(targetLayout.length() - 1); + Settings.System.putString(mActivity.getContentResolver(), Settings.System.LOCKSCREEN_TARGETS, targetLayout.toString()); + for (File pic : mActivity.getFilesDir().listFiles()) { + if (pic.getName().startsWith("lockscreen_") && !existingImages.contains(pic.toString())) { + pic.delete(); + } + } + } + + /** + * Updates a target in the GlowPadView + */ + private void setTarget(int position, String uri, Drawable draw, String iconType, String iconSource, String pkgName) { + TargetInfo item = mTargetStore.get(position); + StateListDrawable state = (StateListDrawable) item.icon; + LayerDrawable inActiveLayer = (LayerDrawable) state.getStateDrawable(0); + LayerDrawable activeLayer = (LayerDrawable) state.getStateDrawable(1); + inActiveLayer.setDrawableByLayerId(1, draw); + boolean isSystem = iconType != null && iconType.equals(GlowPadView.ICON_RESOURCE); + if (!isSystem) { + final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated); + activeLayer.setDrawableByLayerId(0, new InsetDrawable(activeBack, 0, 0, 0, 0)); + activeLayer.setDrawableByLayerId(1, draw); + } else { + InsetDrawable empty = new InsetDrawable(mResources.getDrawable(android.R.color.transparent), 0, 0, 0, 0); + activeLayer.setDrawableByLayerId(1, empty); + int activeId = mResources.getIdentifier(iconSource.replaceAll("_normal", "_activated"), "drawable", "android"); + Drawable back = null; + if (activeId != 0) { + back = mResources.getDrawable(activeId); + activeLayer.setDrawableByLayerId(0, back); + } else { + final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated); + activeLayer.setDrawableByLayerId(0, new InsetDrawable(activeBack, 0, 0, 0, 0)); + } + } + item.defaultIcon = mDialogIcon.getDrawable().getConstantState().newDrawable().mutate(); + item.uri = uri; + item.iconType = iconType; + item.iconSource = iconSource; + item.pkgName = pkgName; + } + + @Override + public void shortcutPicked(String uri, String friendlyName, boolean isApplication) { + try { + Intent i = Intent.parseUri(uri, 0); + PackageManager pm = mActivity.getPackageManager(); + ActivityInfo aInfo = i.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES); + Drawable icon = null; + if (aInfo != null) { + icon = aInfo.loadIcon(pm).mutate(); + } else { + icon = mResources.getDrawable(android.R.drawable.sym_def_app_icon); + } + mDialogLabel.setText(friendlyName); + mDialogLabel.setTag(uri); + mDialogIcon.setImageDrawable(resizeForDialog(icon)); + mDialogIcon.setTag(null); + } catch (Exception e) { + } + } + + private Drawable resizeForDialog(Drawable image) { + int size = (int) mResources.getDimension(android.R.dimen.app_icon_size); + Bitmap d = ((BitmapDrawable)image).getBitmap(); + Bitmap bitmapOrig = Bitmap.createScaledBitmap(d, size, size, false); + return new BitmapDrawable(mResources, bitmapOrig); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + String shortcut_name = null; + if (data != null) { + shortcut_name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); + } + if (shortcut_name != null && shortcut_name.equals(EMPTY_LABEL)) { + mDialogLabel.setText(EMPTY_LABEL); + mDialogLabel.setTag(GlowPadView.EMPTY_TARGET); + mDialogIcon.setImageResource(R.drawable.ic_empty); + } else if (requestCode == IconPicker.REQUEST_PICK_SYSTEM || requestCode == IconPicker.REQUEST_PICK_GALLERY + || requestCode == IconPicker.REQUEST_PICK_ICON_PACK) { + mIconPicker.onActivityResult(requestCode, resultCode, data); + } else if (requestCode != Activity.RESULT_CANCELED && resultCode != Activity.RESULT_CANCELED) { + mPicker.onActivityResult(requestCode, resultCode, data); + } + } + + @Override + public void onGrabbed(View v, int handle) { + } + + @Override + public void onReleased(View v, int handle) { + } + + @Override + public void onTrigger(View v, final int target) { + mTargetIndex = target; + if ((target != 0 && (mIsScreenLarge || !mIsLandscape)) || (target != 2 && !mIsScreenLarge && mIsLandscape)) { + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); + builder.setTitle(R.string.lockscreen_target_edit_title); + builder.setMessage(R.string.lockscreen_target_edit_msg); + View view = View.inflate(mActivity, R.layout.lockscreen_shortcut_dialog, null); + view.findViewById(R.id.icon).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mDialogLabel.getText().equals(EMPTY_LABEL)) { + try { + mImageTmp.createNewFile(); + mImageTmp.setWritable(true, false); + mIconPicker.pickIcon(getId(), mImageTmp); + } catch (IOException e) { + } + } + } + }); + view.findViewById(R.id.label).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mPicker.pickShortcut(new String[] {EMPTY_LABEL}, new ShortcutIconResource[] { + ShortcutIconResource.fromContext(mActivity, android.R.drawable.ic_delete) }, getId()); + } + }); + mDialogIcon = ((ImageButton) view.findViewById(R.id.icon)); + mDialogLabel = ((Button) view.findViewById(R.id.label)); + TargetInfo item = mTargetStore.get(target); + mDialogIcon.setImageDrawable(mTargetStore.get(target).defaultIcon.mutate()); + TargetInfo tmpIcon = new TargetInfo(null); + tmpIcon.iconType = item.iconType; + tmpIcon.iconSource = item.iconSource; + tmpIcon.pkgName = item.pkgName; + mDialogIcon.setTag(tmpIcon); + if (mTargetStore.get(target).uri.equals(GlowPadView.EMPTY_TARGET)) { + mDialogLabel.setText(EMPTY_LABEL); + } else { + mDialogLabel.setText(mPicker.getFriendlyNameForUri(mTargetStore.get(target).uri)); + } + mDialogLabel.setTag(mTargetStore.get(target).uri); + builder.setView(view); + builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + TargetInfo vObject = (TargetInfo) mDialogIcon.getTag(); + String type = null, source = null, pkgName = null; + int targetInset = mTargetInset; + if (vObject != null) { + type = vObject.iconType; + source = vObject.iconSource; + pkgName = vObject.pkgName; + } + if (type != null && type.equals(GlowPadView.ICON_RESOURCE)) { + targetInset = 0; + } + InsetDrawable pD = new InsetDrawable(mDialogIcon.getDrawable(), targetInset, + targetInset, targetInset, targetInset); + setTarget(mTargetIndex, mDialogLabel.getTag().toString(), pD, type, source, pkgName); + } + }); + builder.setNegativeButton(R.string.cancel, null); + builder.setCancelable(false); + AlertDialog dialog = builder.create(); + dialog.show(); + ((TextView)dialog.findViewById(android.R.id.message)).setTextAppearance(mActivity, + android.R.style.TextAppearance_DeviceDefault_Small); + } + } + + @Override + public void onGrabbedStateChange(View v, int handle) { + } + + @Override + public void iconPicked(int requestCode, int resultCode, Intent in) { + Drawable ic = null; + String iconType = null; + String pkgName = null; + String iconSource = null; + if (requestCode == IconPicker.REQUEST_PICK_GALLERY) { + if (resultCode == Activity.RESULT_OK) { + File mImage = new File(mActivity.getFilesDir() + "/lockscreen_" + System.currentTimeMillis() + ".png"); + if (mImageTmp.exists()) { + mImageTmp.renameTo(mImage); + } + mImage.setReadOnly(); + iconType = GlowPadView.ICON_FILE; + iconSource = mImage.toString(); + ic = new BitmapDrawable(getResources(), BitmapFactory.decodeFile(mImage.toString())); + } else { + if (mImageTmp.exists()) { + mImageTmp.delete(); + } + return; + } + } else if (requestCode == IconPicker.REQUEST_PICK_SYSTEM) { + String resourceName = in.getStringExtra(IconPicker.RESOURCE_NAME); + ic = mResources.getDrawable(mResources.getIdentifier(resourceName, "drawable", "android")).mutate(); + iconType = GlowPadView.ICON_RESOURCE; + iconSource = resourceName; + } else if (requestCode == IconPicker.REQUEST_PICK_ICON_PACK && resultCode == Activity.RESULT_OK) { + String resourceName = in.getStringExtra(IconPicker.RESOURCE_NAME); + pkgName = in.getStringExtra(IconPicker.PACKAGE_NAME); + try { + Context rContext = mActivity.createPackageContext(pkgName, 0); + int id = rContext.getResources().getIdentifier(resourceName, "drawable", pkgName); + ic = rContext.getResources().getDrawable(id); + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + iconType = GlowPadView.ICON_RESOURCE; + iconSource = resourceName; + } else { + return; + } + TargetInfo tmpIcon = new TargetInfo(null); + tmpIcon.iconType = iconType; + tmpIcon.iconSource = iconSource; + tmpIcon.pkgName = pkgName; + mDialogIcon.setTag(tmpIcon); + mDialogIcon.setImageDrawable(ic); + } + + @Override + public void onFinishFinalAnimation() { + } +} diff --git a/src/com/android/settings/cyanogenmod/ShortcutPickHelper.java b/src/com/android/settings/cyanogenmod/ShortcutPickHelper.java new file mode 100644 index 0000000..07a4ee1 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/ShortcutPickHelper.java @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2011 The CyanogenMod 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.settings.cyanogenmod; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.Intent.ShortcutIconResource; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; +import android.widget.ExpandableListView; +import android.widget.TextView; + +import com.android.settings.R; +import com.android.settings.cyanogenmod.ShortcutPickHelper.AppExpandableAdapter.GroupInfo; + +public class ShortcutPickHelper { + + private Activity mParent; + private AlertDialog mAlertDialog; + private OnPickListener mListener; + private PackageManager mPackageManager; + private static final int REQUEST_PICK_SHORTCUT = 100; + private static final int REQUEST_PICK_APPLICATION = 101; + private static final int REQUEST_CREATE_SHORTCUT = 102; + private int lastFragmentId; + + public interface OnPickListener { + void shortcutPicked(String uri, String friendlyName, boolean isApplication); + } + + public ShortcutPickHelper(Activity parent, OnPickListener listener) { + mParent = parent; + mPackageManager = mParent.getPackageManager(); + mListener = listener; + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == Activity.RESULT_OK) { + switch (requestCode) { + case REQUEST_PICK_APPLICATION: + completeSetCustomApp(data); + break; + case REQUEST_CREATE_SHORTCUT: + completeSetCustomShortcut(data); + break; + case REQUEST_PICK_SHORTCUT: + processShortcut(data, REQUEST_PICK_APPLICATION, REQUEST_CREATE_SHORTCUT); + break; + } + } + } + + public void pickShortcut(String[] names, ShortcutIconResource[] icons, int fragmentId) { + Bundle bundle = new Bundle(); + + ArrayList<String> shortcutNames = new ArrayList<String>(); + if (names != null) { + for (String s : names) { + shortcutNames.add(s); + } + } + shortcutNames.add(mParent.getString(R.string.profile_applist_title)); + shortcutNames.add(mParent.getString(R.string.picker_activities)); + bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames); + + ArrayList<ShortcutIconResource> shortcutIcons = new ArrayList<ShortcutIconResource>(); + if (icons != null) { + for (ShortcutIconResource s : icons) { + shortcutIcons.add(s); + } + } + shortcutIcons.add(ShortcutIconResource.fromContext(mParent, android.R.drawable.sym_def_app_icon)); + shortcutIcons.add(ShortcutIconResource.fromContext(mParent, R.drawable.activities_icon)); + bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons); + + Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); + pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT)); + pickIntent.putExtra(Intent.EXTRA_TITLE, mParent.getText(R.string.select_custom_app_title)); + pickIntent.putExtras(bundle); + lastFragmentId = fragmentId; + startFragmentOrActivity(pickIntent, REQUEST_PICK_SHORTCUT); + } + + private void startFragmentOrActivity(Intent pickIntent, int requestCode) { + if (lastFragmentId == 0) { + mParent.startActivityForResult(pickIntent, requestCode); + } else { + Fragment cFrag = mParent.getFragmentManager().findFragmentById(lastFragmentId); + if (cFrag != null) { + mParent.startActivityFromFragment(cFrag, pickIntent, requestCode); + } + } + } + + private void processShortcut(final Intent intent, int requestCodeApplication, int requestCodeShortcut) { + // Handle case where user selected "Applications" + String applicationName = mParent.getString(R.string.profile_applist_title); + String application2name = mParent.getString(R.string.picker_activities); + String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); + if (applicationName != null && applicationName.equals(shortcutName)) { + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); + pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent); + startFragmentOrActivity(pickIntent, requestCodeApplication); + } else if (application2name != null && application2name.equals(shortcutName)){ + final List<PackageInfo> pInfos = mPackageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES); + ExpandableListView appListView = new ExpandableListView(mParent); + AppExpandableAdapter appAdapter = new AppExpandableAdapter(pInfos, mParent); + appListView.setAdapter(appAdapter); + appListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { + @Override + public boolean onChildClick(ExpandableListView parent, View v, + int groupPosition, int childPosition, long id) { + Intent shortIntent = new Intent(Intent.ACTION_MAIN); + String pkgName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition)) + .info.packageName; + String actName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition)) + .info.activities[childPosition].name; + shortIntent.setClassName(pkgName, actName); + completeSetCustomApp(shortIntent); + mAlertDialog.dismiss(); + return true; + } + }); + Builder builder = new Builder(mParent); + builder.setView(appListView); + mAlertDialog = builder.create(); + mAlertDialog.setTitle(mParent.getString(R.string.select_custom_activity_title)); + mAlertDialog.show(); + mAlertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mListener.shortcutPicked(null, null, false); + } + }); + } else { + startFragmentOrActivity(intent, requestCodeShortcut); + } + } + + public class AppExpandableAdapter extends BaseExpandableListAdapter { + + ArrayList<GroupInfo> allList = new ArrayList<GroupInfo>(); + final int groupPadding; + + public class LabelCompare implements Comparator<GroupInfo>{ + @Override + public int compare(GroupInfo item1, GroupInfo item2) { + String rank1 = item1.label.toLowerCase(); + String rank2 = item2.label.toLowerCase(); + int result = rank1.compareTo(rank2); + if(result == 0) { + return 0; + } else if(result < 0) { + return -1; + } else { + return +1; + } + } + } + + class GroupInfo { + String label; + PackageInfo info; + GroupInfo (String l, PackageInfo p) { + label = l; + info = p; + } + } + + public AppExpandableAdapter(List<PackageInfo> pInfos, Context context) { + for (PackageInfo i : pInfos) { + allList.add(new GroupInfo(i.applicationInfo.loadLabel(mPackageManager).toString(), i)); + } + Collections.sort(allList, new LabelCompare()); + groupPadding = context.getResources().getDimensionPixelSize(R.dimen.shortcut_picker_left_padding); + } + + public String getChild(int groupPosition, int childPosition) { + return allList.get(groupPosition).info.activities[childPosition].name; + } + + public long getChildId(int groupPosition, int childPosition) { + return childPosition; + } + + public int getChildrenCount(int groupPosition) { + if (allList.get(groupPosition).info.activities != null) { + return allList.get(groupPosition).info.activities.length; + } else { + return 0; + } + } + + + public View getChildView(int groupPosition, int childPosition, boolean isLastChild, + View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null); + convertView.setPadding(groupPadding, 0, 0, 0); + + } + TextView textView = (TextView)convertView.findViewById(android.R.id.text1); + textView.setText(getChild(groupPosition, childPosition).replaceFirst(allList.get(groupPosition).info.packageName + ".", "")); + return convertView; + } + + public GroupInfo getGroup(int groupPosition) { + return allList.get(groupPosition); + } + + public int getGroupCount() { + return allList.size(); + } + + public long getGroupId(int groupPosition) { + return groupPosition; + } + + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, + ViewGroup parent) { + if (convertView == null) { + convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null); + convertView.setPadding(70, 0, 0, 0); + } + TextView textView = (TextView)convertView.findViewById(android.R.id.text1); + textView.setText(getGroup(groupPosition).label.toString()); + return convertView; + } + + public boolean isChildSelectable(int groupPosition, int childPosition) { + return true; + } + + public boolean hasStableIds() { + return true; + } + + } + + private void completeSetCustomApp(Intent data) { + mListener.shortcutPicked(data.toUri(0), getFriendlyActivityName(data, false), true); + } + + private void completeSetCustomShortcut(Intent data) { + Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); + /* preserve shortcut name, we want to restore it later */ + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME)); + String appUri = intent.toUri(0); + appUri = appUri.replaceAll("com.android.contacts.action.QUICK_CONTACT", "android.intent.action.VIEW"); + mListener.shortcutPicked(appUri, getFriendlyShortcutName(intent), false); + } + + private String getFriendlyActivityName(Intent intent, boolean labelOnly) { + ActivityInfo ai = intent.resolveActivityInfo(mPackageManager, PackageManager.GET_ACTIVITIES); + String friendlyName = null; + if (ai != null) { + friendlyName = ai.loadLabel(mPackageManager).toString(); + if (friendlyName == null && !labelOnly) { + friendlyName = ai.name; + } + } + return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0); + } + + private String getFriendlyShortcutName(Intent intent) { + String activityName = getFriendlyActivityName(intent, true); + String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); + + if (activityName != null && name != null) { + return activityName + ": " + name; + } + return name != null ? name : intent.toUri(0); + } + + public String getFriendlyNameForUri(String uri) { + if (uri == null) { + return null; + } + + try { + Intent intent = Intent.parseUri(uri, 0); + if (Intent.ACTION_MAIN.equals(intent.getAction())) { + return getFriendlyActivityName(intent, false); + } + return getFriendlyShortcutName(intent); + } catch (URISyntaxException e) { + } + + return uri; + } +}
\ No newline at end of file |