1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.Dialog; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.os.Bundle; 28 import android.util.Log; 29 import android.view.LayoutInflater; 30 import android.view.Menu; 31 import android.view.MenuInflater; 32 import android.view.MenuItem; 33 import android.view.MenuItem.OnMenuItemClickListener; 34 import android.view.MotionEvent; 35 import android.view.View; 36 import android.view.View.OnClickListener; 37 import android.view.View.OnTouchListener; 38 import android.view.ViewGroup; 39 import android.widget.ArrayAdapter; 40 import android.widget.ImageView; 41 import android.widget.ListView; 42 import android.widget.RadioButton; 43 import android.widget.Switch; 44 import android.widget.TextView; 45 46 import com.android.settings.DreamBackend.DreamInfo; 47 import com.android.settings.widget.SwitchBar; 48 49 import java.util.List; 50 51 public class DreamSettings extends SettingsPreferenceFragment implements 52 SwitchBar.OnSwitchChangeListener { 53 private static final String TAG = DreamSettings.class.getSimpleName(); 54 static final boolean DEBUG = false; 55 private static final int DIALOG_WHEN_TO_DREAM = 1; 56 private static final String PACKAGE_SCHEME = "package"; 57 58 private final PackageReceiver mPackageReceiver = new PackageReceiver(); 59 60 private Context mContext; 61 private DreamBackend mBackend; 62 private DreamInfoAdapter mAdapter; 63 private SwitchBar mSwitchBar; 64 private MenuItem[] mMenuItemsWhenEnabled; 65 private boolean mRefreshing; 66 67 @Override getHelpResource()68 public int getHelpResource() { 69 return R.string.help_url_dreams; 70 } 71 72 @Override onAttach(Activity activity)73 public void onAttach(Activity activity) { 74 logd("onAttach(%s)", activity.getClass().getSimpleName()); 75 super.onAttach(activity); 76 mContext = activity; 77 } 78 79 @Override onCreate(Bundle icicle)80 public void onCreate(Bundle icicle) { 81 logd("onCreate(%s)", icicle); 82 super.onCreate(icicle); 83 84 mBackend = new DreamBackend(getActivity()); 85 86 setHasOptionsMenu(true); 87 } 88 89 @Override onSwitchChanged(Switch switchView, boolean isChecked)90 public void onSwitchChanged(Switch switchView, boolean isChecked) { 91 if (!mRefreshing) { 92 mBackend.setEnabled(isChecked); 93 refreshFromBackend(); 94 } 95 } 96 97 @Override onStart()98 public void onStart() { 99 logd("onStart()"); 100 super.onStart(); 101 } 102 103 @Override onDestroyView()104 public void onDestroyView() { 105 logd("onDestroyView()"); 106 super.onDestroyView(); 107 108 mSwitchBar.removeOnSwitchChangeListener(this); 109 mSwitchBar.hide(); 110 } 111 112 @Override onActivityCreated(Bundle savedInstanceState)113 public void onActivityCreated(Bundle savedInstanceState) { 114 logd("onActivityCreated(%s)", savedInstanceState); 115 super.onActivityCreated(savedInstanceState); 116 117 ListView listView = getListView(); 118 listView.setItemsCanFocus(true); 119 120 TextView emptyView = (TextView) getView().findViewById(android.R.id.empty); 121 emptyView.setText(R.string.screensaver_settings_disabled_prompt); 122 listView.setEmptyView(emptyView); 123 124 mAdapter = new DreamInfoAdapter(mContext); 125 listView.setAdapter(mAdapter); 126 127 final SettingsActivity sa = (SettingsActivity) getActivity(); 128 mSwitchBar = sa.getSwitchBar(); 129 mSwitchBar.addOnSwitchChangeListener(this); 130 mSwitchBar.show(); 131 } 132 133 @Override onCreateOptionsMenu(Menu menu, MenuInflater inflater)134 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 135 logd("onCreateOptionsMenu()"); 136 137 boolean isEnabled = mBackend.isEnabled(); 138 139 // create "start" action 140 MenuItem start = createMenuItem(menu, R.string.screensaver_settings_dream_start, 141 MenuItem.SHOW_AS_ACTION_NEVER, 142 isEnabled, new Runnable(){ 143 @Override 144 public void run() { 145 mBackend.startDreaming(); 146 }}); 147 148 // create "when to dream" overflow menu item 149 MenuItem whenToDream = createMenuItem(menu, 150 R.string.screensaver_settings_when_to_dream, 151 MenuItem.SHOW_AS_ACTION_NEVER, 152 isEnabled, 153 new Runnable() { 154 @Override 155 public void run() { 156 showDialog(DIALOG_WHEN_TO_DREAM); 157 }}); 158 159 // create "help" overflow menu item (make sure it appears last) 160 super.onCreateOptionsMenu(menu, inflater); 161 162 mMenuItemsWhenEnabled = new MenuItem[] { start, whenToDream }; 163 } 164 createMenuItem(Menu menu, int titleRes, int actionEnum, boolean isEnabled, final Runnable onClick)165 private MenuItem createMenuItem(Menu menu, 166 int titleRes, int actionEnum, boolean isEnabled, final Runnable onClick) { 167 MenuItem item = menu.add(titleRes); 168 item.setShowAsAction(actionEnum); 169 item.setEnabled(isEnabled); 170 item.setOnMenuItemClickListener(new OnMenuItemClickListener() { 171 @Override 172 public boolean onMenuItemClick(MenuItem item) { 173 onClick.run(); 174 return true; 175 } 176 }); 177 return item; 178 } 179 180 @Override onCreateDialog(int dialogId)181 public Dialog onCreateDialog(int dialogId) { 182 logd("onCreateDialog(%s)", dialogId); 183 if (dialogId == DIALOG_WHEN_TO_DREAM) 184 return createWhenToDreamDialog(); 185 return super.onCreateDialog(dialogId); 186 } 187 createWhenToDreamDialog()188 private Dialog createWhenToDreamDialog() { 189 final CharSequence[] items = { 190 mContext.getString(R.string.screensaver_settings_summary_dock), 191 mContext.getString(R.string.screensaver_settings_summary_sleep), 192 mContext.getString(R.string.screensaver_settings_summary_either_short) 193 }; 194 195 int initialSelection = mBackend.isActivatedOnDock() && mBackend.isActivatedOnSleep() ? 2 196 : mBackend.isActivatedOnDock() ? 0 197 : mBackend.isActivatedOnSleep() ? 1 198 : -1; 199 200 return new AlertDialog.Builder(mContext) 201 .setTitle(R.string.screensaver_settings_when_to_dream) 202 .setSingleChoiceItems(items, initialSelection, new DialogInterface.OnClickListener() { 203 public void onClick(DialogInterface dialog, int item) { 204 mBackend.setActivatedOnDock(item == 0 || item == 2); 205 mBackend.setActivatedOnSleep(item == 1 || item == 2); 206 dialog.dismiss(); 207 } 208 }) 209 .create(); 210 } 211 212 @Override 213 public void onPause() { 214 logd("onPause()"); 215 super.onPause(); 216 217 mContext.unregisterReceiver(mPackageReceiver); 218 } 219 220 @Override 221 public void onResume() { 222 logd("onResume()"); 223 super.onResume(); 224 refreshFromBackend(); 225 226 // listen for package changes 227 IntentFilter filter = new IntentFilter(); 228 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 229 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 230 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 231 filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 232 filter.addDataScheme(PACKAGE_SCHEME); 233 mContext.registerReceiver(mPackageReceiver , filter); 234 } 235 236 public static int getSummaryResource(Context context) { 237 DreamBackend backend = new DreamBackend(context); 238 boolean isEnabled = backend.isEnabled(); 239 boolean activatedOnSleep = backend.isActivatedOnSleep(); 240 boolean activatedOnDock = backend.isActivatedOnDock(); 241 boolean activatedOnEither = activatedOnSleep && activatedOnDock; 242 return !isEnabled ? R.string.screensaver_settings_summary_off 243 : activatedOnEither ? R.string.screensaver_settings_summary_either_long 244 : activatedOnSleep ? R.string.screensaver_settings_summary_sleep 245 : activatedOnDock ? R.string.screensaver_settings_summary_dock 246 : 0; 247 } 248 249 public static CharSequence getSummaryTextWithDreamName(Context context) { 250 DreamBackend backend = new DreamBackend(context); 251 boolean isEnabled = backend.isEnabled(); 252 if (!isEnabled) { 253 return context.getString(R.string.screensaver_settings_summary_off); 254 } else { 255 return backend.getActiveDreamName(); 256 } 257 } 258 259 private void refreshFromBackend() { 260 logd("refreshFromBackend()"); 261 mRefreshing = true; 262 boolean dreamsEnabled = mBackend.isEnabled(); 263 if (mSwitchBar.isChecked() != dreamsEnabled) 264 mSwitchBar.setChecked(dreamsEnabled); 265 266 mAdapter.clear(); 267 if (dreamsEnabled) { 268 List<DreamInfo> dreamInfos = mBackend.getDreamInfos(); 269 mAdapter.addAll(dreamInfos); 270 } 271 if (mMenuItemsWhenEnabled != null) 272 for (MenuItem menuItem : mMenuItemsWhenEnabled) 273 menuItem.setEnabled(dreamsEnabled); 274 mRefreshing = false; 275 } 276 277 private static void logd(String msg, Object... args) { 278 if (DEBUG) 279 Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args)); 280 } 281 282 private class DreamInfoAdapter extends ArrayAdapter<DreamInfo> { 283 private final LayoutInflater mInflater; 284 285 public DreamInfoAdapter(Context context) { 286 super(context, 0); 287 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 288 } 289 290 @Override 291 public View getView(int position, View convertView, ViewGroup parent) { 292 DreamInfo dreamInfo = getItem(position); 293 logd("getView(%s)", dreamInfo.caption); 294 final View row = convertView != null ? convertView : createDreamInfoRow(parent); 295 row.setTag(dreamInfo); 296 297 // bind icon 298 ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(dreamInfo.icon); 299 300 // bind caption 301 ((TextView) row.findViewById(android.R.id.title)).setText(dreamInfo.caption); 302 303 // bind radio button 304 RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1); 305 radioButton.setChecked(dreamInfo.isActive); 306 radioButton.setOnTouchListener(new OnTouchListener() { 307 @Override 308 public boolean onTouch(View v, MotionEvent event) { 309 row.onTouchEvent(event); 310 return false; 311 }}); 312 313 // bind settings button + divider 314 boolean showSettings = dreamInfo.settingsComponentName != null; 315 View settingsDivider = row.findViewById(R.id.divider); 316 settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); 317 318 ImageView settingsButton = (ImageView) row.findViewById(android.R.id.button2); 319 settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE); 320 settingsButton.setAlpha(dreamInfo.isActive ? 1f : Utils.DISABLED_ALPHA); 321 settingsButton.setEnabled(dreamInfo.isActive); 322 settingsButton.setFocusable(dreamInfo.isActive); 323 settingsButton.setOnClickListener(new OnClickListener(){ 324 @Override 325 public void onClick(View v) { 326 mBackend.launchSettings((DreamInfo) row.getTag()); 327 }}); 328 329 return row; 330 } 331 332 private View createDreamInfoRow(ViewGroup parent) { 333 final View row = mInflater.inflate(R.layout.dream_info_row, parent, false); 334 final View header = row.findViewById(android.R.id.widget_frame); 335 header.setOnClickListener(new OnClickListener(){ 336 @Override 337 public void onClick(View v) { 338 v.setPressed(true); 339 activate((DreamInfo) row.getTag()); 340 }}); 341 return row; 342 } 343 344 private DreamInfo getCurrentSelection() { 345 for (int i = 0; i < getCount(); i++) { 346 DreamInfo dreamInfo = getItem(i); 347 if (dreamInfo.isActive) 348 return dreamInfo; 349 } 350 return null; 351 } 352 private void activate(DreamInfo dreamInfo) { 353 if (dreamInfo.equals(getCurrentSelection())) 354 return; 355 for (int i = 0; i < getCount(); i++) { 356 getItem(i).isActive = false; 357 } 358 dreamInfo.isActive = true; 359 mBackend.setActiveDream(dreamInfo.componentName); 360 notifyDataSetChanged(); 361 } 362 } 363 364 private class PackageReceiver extends BroadcastReceiver { 365 @Override 366 public void onReceive(Context context, Intent intent) { 367 logd("PackageReceiver.onReceive"); 368 refreshFromBackend(); 369 } 370 } 371 } 372