DeskClock.java revision 40bf69f36896140231b260827d96e9f4aaa6aa3f
1/* 2 * Copyright (C) 2009 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 17package com.android.deskclock; 18 19import android.animation.ArgbEvaluator; 20import android.animation.ObjectAnimator; 21import android.app.ActionBar; 22import android.app.ActionBar.Tab; 23import android.app.Activity; 24import android.app.Fragment; 25import android.app.FragmentManager; 26import android.app.FragmentTransaction; 27import android.content.ActivityNotFoundException; 28import android.content.Context; 29import android.content.Intent; 30import android.content.SharedPreferences; 31import android.content.res.Configuration; 32import android.graphics.Outline; 33import android.os.Bundle; 34import android.os.Handler; 35import android.preference.PreferenceManager; 36import android.support.v13.app.FragmentPagerAdapter; 37import android.support.v4.view.ViewPager; 38import android.text.TextUtils; 39import android.text.format.DateUtils; 40import android.util.Log; 41import android.view.Menu; 42import android.view.MenuItem; 43import android.view.MotionEvent; 44import android.view.View; 45import android.view.View.OnClickListener; 46import android.view.View.OnTouchListener; 47import android.view.ViewOutlineProvider; 48import android.widget.ImageButton; 49import android.widget.TextView; 50 51import com.android.deskclock.alarms.AlarmStateManager; 52import com.android.deskclock.provider.Alarm; 53import com.android.deskclock.stopwatch.StopwatchFragment; 54import com.android.deskclock.stopwatch.StopwatchService; 55import com.android.deskclock.stopwatch.Stopwatches; 56import com.android.deskclock.timer.TimerFragment; 57import com.android.deskclock.timer.TimerObj; 58import com.android.deskclock.timer.Timers; 59 60import java.util.ArrayList; 61import java.util.HashSet; 62import java.util.Locale; 63import java.util.TimeZone; 64 65/** 66 * DeskClock clock view for desk docks. 67 */ 68public class DeskClock extends Activity implements LabelDialogFragment.TimerLabelDialogHandler, 69 LabelDialogFragment.AlarmLabelDialogHandler { 70 private static final boolean DEBUG = false; 71 private static final String LOG_TAG = "DeskClock"; 72 // Alarm action for midnight (so we can update the date display). 73 private static final String KEY_SELECTED_TAB = "selected_tab"; 74 private static final String KEY_LAST_HOUR_COLOR = "last_hour_color"; 75 // Check whether to change background every minute 76 private static final long BACKGROUND_COLOR_CHECK_DELAY_MILLIS = DateUtils.MINUTE_IN_MILLIS; 77 private static final int BACKGROUND_COLOR_INITIAL_ANIMATION_DURATION_MILLIS = 3000; 78 // The depth of fab, use it to create shadow 79 private static final float FAB_DEPTH = 20f; 80 private static final int UNKNOWN_COLOR_ID = 0; 81 82 private boolean mIsFirstLaunch; 83 private ActionBar mActionBar; 84 private Tab mAlarmTab; 85 private Tab mClockTab; 86 private Tab mTimerTab; 87 private Tab mStopwatchTab; 88 private Menu mMenu; 89 private ViewPager mViewPager; 90 private TabsAdapter mTabsAdapter; 91 private Handler mHander; 92 public ImageButton mFab; 93 private int mSelectedTab; 94 private int mLastHourColor = UNKNOWN_COLOR_ID; 95 private final Runnable mBackgroundColorChanger = new Runnable() { 96 @Override 97 public void run() { 98 setBackgroundColor(); 99 mHander.postDelayed(this, BACKGROUND_COLOR_CHECK_DELAY_MILLIS); 100 } 101 }; 102 103 public static final int ALARM_TAB_INDEX = 0; 104 public static final int CLOCK_TAB_INDEX = 1; 105 public static final int TIMER_TAB_INDEX = 2; 106 public static final int STOPWATCH_TAB_INDEX = 3; 107 // Tabs indices are switched for right-to-left since there is no 108 // native support for RTL in the ViewPager. 109 public static final int RTL_ALARM_TAB_INDEX = 3; 110 public static final int RTL_CLOCK_TAB_INDEX = 2; 111 public static final int RTL_TIMER_TAB_INDEX = 1; 112 public static final int RTL_STOPWATCH_TAB_INDEX = 0; 113 public static final String SELECT_TAB_INTENT_EXTRA = "deskclock.select.tab"; 114 115 // TODO(rachelzhang): adding a broadcast receiver to adjust color when the timezone/time 116 // changes in the background. 117 118 @Override 119 protected void onStart() { 120 super.onStart(); 121 if (mHander == null) { 122 mHander = new Handler(); 123 } 124 mHander.postDelayed(mBackgroundColorChanger, BACKGROUND_COLOR_CHECK_DELAY_MILLIS); 125 } 126 127 @Override 128 protected void onStop() { 129 super.onStop(); 130 mHander.removeCallbacks(mBackgroundColorChanger); 131 } 132 133 @Override 134 public void onNewIntent(Intent newIntent) { 135 super.onNewIntent(newIntent); 136 if (DEBUG) Log.d(LOG_TAG, "onNewIntent with intent: " + newIntent); 137 138 // update our intent so that we can consult it to determine whether or 139 // not the most recent launch was via a dock event 140 setIntent(newIntent); 141 142 // Timer receiver may ask to go to the timers fragment if a timer expired. 143 int tab = newIntent.getIntExtra(SELECT_TAB_INTENT_EXTRA, -1); 144 if (tab != -1) { 145 if (mActionBar != null) { 146 mActionBar.setSelectedNavigationItem(tab); 147 } 148 } 149 } 150 151 private static final ViewOutlineProvider OVAL_OUTLINE_PROVIDER = new ViewOutlineProvider() { 152 @Override 153 public void getOutline(View view, Outline outline) { 154 outline.setOval(0, 0, view.getWidth(), view.getHeight()); 155 } 156 }; 157 158 private void initViews() { 159 setContentView(R.layout.desk_clock); 160 mFab = (ImageButton) findViewById(R.id.fab); 161 mFab.setOutlineProvider(OVAL_OUTLINE_PROVIDER); 162 mFab.setTranslationZ(FAB_DEPTH); 163 if (mTabsAdapter == null) { 164 mViewPager = (ViewPager) findViewById(R.id.desk_clock_pager); 165 // Keep all four tabs to minimize jank. 166 mViewPager.setOffscreenPageLimit(3); 167 mTabsAdapter = new TabsAdapter(this, mViewPager); 168 createTabs(mSelectedTab); 169 } 170 171 mFab.setOnClickListener(new OnClickListener() { 172 @Override 173 public void onClick(View view) { 174 DeskClockFragment fragment = (DeskClockFragment) mTabsAdapter.getItem( 175 getRtlPosition(mSelectedTab)); 176 fragment.respondClick(view); 177 } 178 }); 179 180 mActionBar.setSelectedNavigationItem(mSelectedTab); 181 } 182 183 private void createTabs(int selectedIndex) { 184 mActionBar = getActionBar(); 185 186 if (mActionBar != null) { 187 mActionBar.setDisplayOptions(0); 188 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 189 190 mAlarmTab = mActionBar.newTab(); 191 mAlarmTab.setIcon(R.drawable.alarm_tab); 192 mAlarmTab.setContentDescription(R.string.menu_alarm); 193 mTabsAdapter.addTab(mAlarmTab, AlarmClockFragment.class, ALARM_TAB_INDEX); 194 195 mClockTab = mActionBar.newTab(); 196 mClockTab.setIcon(R.drawable.clock_tab); 197 mClockTab.setContentDescription(R.string.menu_clock); 198 mTabsAdapter.addTab(mClockTab, ClockFragment.class, CLOCK_TAB_INDEX); 199 200 mTimerTab = mActionBar.newTab(); 201 mTimerTab.setIcon(R.drawable.timer_tab); 202 mTimerTab.setContentDescription(R.string.menu_timer); 203 mTabsAdapter.addTab(mTimerTab, TimerFragment.class, TIMER_TAB_INDEX); 204 205 mStopwatchTab = mActionBar.newTab(); 206 mStopwatchTab.setIcon(R.drawable.stopwatch_tab); 207 mStopwatchTab.setContentDescription(R.string.menu_stopwatch); 208 mTabsAdapter.addTab(mStopwatchTab, StopwatchFragment.class, STOPWATCH_TAB_INDEX); 209 210 mActionBar.setSelectedNavigationItem(selectedIndex); 211 mTabsAdapter.notifySelectedPage(selectedIndex); 212 } 213 } 214 215 @Override 216 protected void onCreate(Bundle icicle) { 217 super.onCreate(icicle); 218 219 getWindow().setBackgroundDrawable(null); 220 221 mIsFirstLaunch = true; 222 mSelectedTab = CLOCK_TAB_INDEX; 223 if (icicle != null) { 224 mSelectedTab = icicle.getInt(KEY_SELECTED_TAB, CLOCK_TAB_INDEX); 225 mLastHourColor = icicle.getInt(KEY_LAST_HOUR_COLOR, UNKNOWN_COLOR_ID); 226 if (mLastHourColor != UNKNOWN_COLOR_ID) { 227 getWindow().getDecorView().setBackgroundColor(mLastHourColor); 228 } 229 } 230 231 // Timer receiver may ask the app to go to the timer fragment if a timer expired 232 Intent i = getIntent(); 233 if (i != null) { 234 int tab = i.getIntExtra(SELECT_TAB_INTENT_EXTRA, -1); 235 if (tab != -1) { 236 mSelectedTab = tab; 237 } 238 } 239 initViews(); 240 setHomeTimeZone(); 241 242 // We need to update the system next alarm time on app startup because the 243 // user might have clear our data. 244 AlarmStateManager.updateNextAlarm(this); 245 ExtensionsFactory.init(getAssets()); 246 } 247 248 @Override 249 protected void onResume() { 250 super.onResume(); 251 252 setBackgroundColor(); 253 254 // We only want to show notifications for stopwatch/timer when the app is closed so 255 // that we don't have to worry about keeping the notifications in perfect sync with 256 // the app. 257 Intent stopwatchIntent = new Intent(getApplicationContext(), StopwatchService.class); 258 stopwatchIntent.setAction(Stopwatches.KILL_NOTIF); 259 startService(stopwatchIntent); 260 261 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 262 SharedPreferences.Editor editor = prefs.edit(); 263 editor.putBoolean(Timers.NOTIF_APP_OPEN, true); 264 editor.apply(); 265 Intent timerIntent = new Intent(); 266 timerIntent.setAction(Timers.NOTIF_IN_USE_CANCEL); 267 sendBroadcast(timerIntent); 268 } 269 270 @Override 271 public void onPause() { 272 Intent intent = new Intent(getApplicationContext(), StopwatchService.class); 273 intent.setAction(Stopwatches.SHOW_NOTIF); 274 startService(intent); 275 276 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 277 SharedPreferences.Editor editor = prefs.edit(); 278 editor.putBoolean(Timers.NOTIF_APP_OPEN, false); 279 editor.apply(); 280 Utils.showInUseNotifications(this); 281 282 super.onPause(); 283 } 284 285 @Override 286 protected void onSaveInstanceState(Bundle outState) { 287 super.onSaveInstanceState(outState); 288 outState.putInt(KEY_SELECTED_TAB, mActionBar.getSelectedNavigationIndex()); 289 outState.putInt(KEY_LAST_HOUR_COLOR, mLastHourColor); 290 } 291 292 @Override 293 public boolean onCreateOptionsMenu(Menu menu) { 294 // We only want to show it as a menu in landscape, and only for clock/alarm fragment. 295 mMenu = menu; 296 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 297 if (mActionBar.getSelectedNavigationIndex() == ALARM_TAB_INDEX || 298 mActionBar.getSelectedNavigationIndex() == CLOCK_TAB_INDEX) { 299 // Clear the menu so that it doesn't get duplicate items in case onCreateOptionsMenu 300 // was called multiple times. 301 menu.clear(); 302 getMenuInflater().inflate(R.menu.desk_clock_menu, menu); 303 } 304 // Always return true for landscape, regardless of whether we've inflated the menu, so 305 // that when we switch tabs this method will get called and we can inflate the menu. 306 return true; 307 } 308 return false; 309 } 310 311 @Override 312 public boolean onPrepareOptionsMenu(Menu menu) { 313 updateMenu(menu); 314 return true; 315 } 316 317 private void updateMenu(Menu menu) { 318 // Hide "help" if we don't have a URI for it. 319 MenuItem help = menu.findItem(R.id.menu_item_help); 320 if (help != null) { 321 Utils.prepareHelpMenuItem(this, help); 322 } 323 324 // Hide "lights out" for timer. 325 MenuItem nightMode = menu.findItem(R.id.menu_item_night_mode); 326 if (mActionBar.getSelectedNavigationIndex() == ALARM_TAB_INDEX) { 327 nightMode.setVisible(false); 328 } else if (mActionBar.getSelectedNavigationIndex() == CLOCK_TAB_INDEX) { 329 nightMode.setVisible(true); 330 } 331 } 332 333 @Override 334 public boolean onOptionsItemSelected(MenuItem item) { 335 if (processMenuClick(item)) { 336 return true; 337 } 338 339 return super.onOptionsItemSelected(item); 340 } 341 342 private boolean processMenuClick(MenuItem item) { 343 switch (item.getItemId()) { 344 case R.id.menu_item_settings: 345 startActivity(new Intent(DeskClock.this, SettingsActivity.class)); 346 return true; 347 case R.id.menu_item_help: 348 Intent i = item.getIntent(); 349 if (i != null) { 350 try { 351 startActivity(i); 352 } catch (ActivityNotFoundException e) { 353 // No activity found to match the intent - ignore 354 } 355 } 356 return true; 357 case R.id.menu_item_night_mode: 358 startActivity(new Intent(DeskClock.this, ScreensaverActivity.class)); 359 default: 360 break; 361 } 362 return true; 363 } 364 365 /** 366 * Insert the local time zone as the Home Time Zone if one is not set 367 */ 368 private void setHomeTimeZone() { 369 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 370 String homeTimeZone = prefs.getString(SettingsActivity.KEY_HOME_TZ, ""); 371 if (!homeTimeZone.isEmpty()) { 372 return; 373 } 374 homeTimeZone = TimeZone.getDefault().getID(); 375 SharedPreferences.Editor editor = prefs.edit(); 376 editor.putString(SettingsActivity.KEY_HOME_TZ, homeTimeZone); 377 editor.apply(); 378 Log.v(LOG_TAG, "Setting home time zone to " + homeTimeZone); 379 } 380 381 public void registerPageChangedListener(DeskClockFragment frag) { 382 if (mTabsAdapter != null) { 383 mTabsAdapter.registerPageChangedListener(frag); 384 } 385 } 386 387 public void unregisterPageChangedListener(DeskClockFragment frag) { 388 if (mTabsAdapter != null) { 389 mTabsAdapter.unregisterPageChangedListener(frag); 390 } 391 } 392 393 private void setBackgroundColor() { 394 final int duration; 395 if (mLastHourColor == UNKNOWN_COLOR_ID) { 396 mLastHourColor = getResources().getColor(R.color.default_background); 397 duration = BACKGROUND_COLOR_INITIAL_ANIMATION_DURATION_MILLIS; 398 } else { 399 duration = getResources().getInteger(android.R.integer.config_longAnimTime); 400 } 401 final int currHourColor = Utils.getCurrentHourColor(); 402 if (mLastHourColor != currHourColor) { 403 final ObjectAnimator animator = ObjectAnimator.ofInt(getWindow().getDecorView(), 404 "backgroundColor", mLastHourColor, currHourColor); 405 animator.setDuration(duration); 406 animator.setEvaluator(new ArgbEvaluator()); 407 animator.start(); 408 mLastHourColor = currHourColor; 409 } 410 } 411 412 /** 413 * Adapter for wrapping together the ActionBar's tab with the ViewPager 414 */ 415 416 private class TabsAdapter extends FragmentPagerAdapter 417 implements ActionBar.TabListener, ViewPager.OnPageChangeListener { 418 419 private static final String KEY_TAB_POSITION = "tab_position"; 420 421 final class TabInfo { 422 private final Class<?> clss; 423 private final Bundle args; 424 425 TabInfo(Class<?> _class, int position) { 426 clss = _class; 427 args = new Bundle(); 428 args.putInt(KEY_TAB_POSITION, position); 429 } 430 431 public int getPosition() { 432 return args.getInt(KEY_TAB_POSITION, 0); 433 } 434 } 435 436 private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 437 ActionBar mMainActionBar; 438 Context mContext; 439 ViewPager mPager; 440 // Used for doing callbacks to fragments. 441 HashSet<String> mFragmentTags = new HashSet<String>(); 442 443 public TabsAdapter(Activity activity, ViewPager pager) { 444 super(activity.getFragmentManager()); 445 mContext = activity; 446 mMainActionBar = activity.getActionBar(); 447 mPager = pager; 448 mPager.setAdapter(this); 449 mPager.setOnPageChangeListener(this); 450 } 451 452 @Override 453 public Fragment getItem(int position) { 454 // Because this public method is called outside many times, 455 // check if it exits first before creating a new one. 456 final String name = makeFragmentName(R.id.desk_clock_pager, position); 457 Fragment fragment = getFragmentManager().findFragmentByTag(name); 458 if (fragment == null) { 459 TabInfo info = mTabs.get(getRtlPosition(position)); 460 fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args); 461 } 462 463 return fragment; 464 465 } 466 467 /** 468 * Copied from: 469 * android/frameworks/support/v13/java/android/support/v13/app/FragmentPagerAdapter.java#94 470 * Create unique name for the fragment so fragment manager knows it exist. 471 */ 472 private String makeFragmentName(int viewId, int index) { 473 return "android:switcher:" + viewId + ":" + index; 474 } 475 476 @Override 477 public int getCount() { 478 return mTabs.size(); 479 } 480 481 public void addTab(ActionBar.Tab tab, Class<?> clss, int position) { 482 TabInfo info = new TabInfo(clss, position); 483 tab.setTag(info); 484 tab.setTabListener(this); 485 mTabs.add(info); 486 mMainActionBar.addTab(tab); 487 notifyDataSetChanged(); 488 } 489 490 @Override 491 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 492 // Do nothing 493 } 494 495 @Override 496 public void onPageSelected(int position) { 497 // Set the page before doing the menu so that onCreateOptionsMenu knows what page it is. 498 mMainActionBar.setSelectedNavigationItem(getRtlPosition(position)); 499 notifyPageChanged(position); 500 501 // Only show the overflow menu for alarm and world clock. 502 if (mMenu != null) { 503 // Make sure the menu's been initialized. 504 if (position == ALARM_TAB_INDEX || position == CLOCK_TAB_INDEX) { 505 mMenu.setGroupVisible(R.id.menu_items, true); 506 onCreateOptionsMenu(mMenu); 507 } else { 508 mMenu.setGroupVisible(R.id.menu_items, false); 509 } 510 } 511 } 512 513 @Override 514 public void onPageScrollStateChanged(int state) { 515 // Do nothing 516 } 517 518 @Override 519 public void onTabReselected(Tab arg0, FragmentTransaction arg1) { 520 // Do nothing 521 } 522 523 @Override 524 public void onTabSelected(Tab tab, FragmentTransaction ft) { 525 TabInfo info = (TabInfo) tab.getTag(); 526 int position = info.getPosition(); 527 mSelectedTab = position; 528 if (mIsFirstLaunch && getRtlPosition(position) == CLOCK_TAB_INDEX) { 529 mFab.setVisibility(View.VISIBLE); 530 mFab.setImageResource(R.drawable.ic_globe); 531 mFab.setContentDescription(getString(R.string.button_cities)); 532 mIsFirstLaunch = false; 533 } else { 534 DeskClockFragment f = (DeskClockFragment) getItem(getRtlPosition(position)); 535 f.setFabAppearance(mFab); 536 } 537 mPager.setCurrentItem(getRtlPosition(position)); 538 } 539 540 @Override 541 public void onTabUnselected(Tab arg0, FragmentTransaction arg1) { 542 // Do nothing 543 } 544 545 public void notifySelectedPage(int page) { 546 notifyPageChanged(page); 547 } 548 549 private void notifyPageChanged(int newPage) { 550 for (String tag : mFragmentTags) { 551 final FragmentManager fm = getFragmentManager(); 552 DeskClockFragment f = (DeskClockFragment) fm.findFragmentByTag(tag); 553 if (f != null) { 554 f.onPageChanged(newPage); 555 } 556 } 557 } 558 559 public void registerPageChangedListener(DeskClockFragment frag) { 560 String tag = frag.getTag(); 561 if (mFragmentTags.contains(tag)) { 562 Log.wtf(LOG_TAG, "Trying to add an existing fragment " + tag); 563 } else { 564 mFragmentTags.add(frag.getTag()); 565 } 566 // Since registering a listener by the fragment is done sometimes after the page 567 // was already changed, make sure the fragment gets the current page 568 frag.onPageChanged(mMainActionBar.getSelectedNavigationIndex()); 569 } 570 571 public void unregisterPageChangedListener(DeskClockFragment frag) { 572 mFragmentTags.remove(frag.getTag()); 573 } 574 575 } 576 577 public static abstract class OnTapListener implements OnTouchListener { 578 private float mLastTouchX; 579 private float mLastTouchY; 580 private long mLastTouchTime; 581 private final TextView mMakePressedTextView; 582 private final int mPressedColor, mGrayColor; 583 private final float MAX_MOVEMENT_ALLOWED = 20; 584 private final long MAX_TIME_ALLOWED = 500; 585 586 public OnTapListener(Activity activity, TextView makePressedView) { 587 mMakePressedTextView = makePressedView; 588 mPressedColor = activity.getResources().getColor(Utils.getPressedColorId()); 589 mGrayColor = activity.getResources().getColor(Utils.getGrayColorId()); 590 } 591 592 @Override 593 public boolean onTouch(View v, MotionEvent e) { 594 switch (e.getAction()) { 595 case (MotionEvent.ACTION_DOWN): 596 mLastTouchTime = Utils.getTimeNow(); 597 mLastTouchX = e.getX(); 598 mLastTouchY = e.getY(); 599 if (mMakePressedTextView != null) { 600 mMakePressedTextView.setTextColor(mPressedColor); 601 } 602 break; 603 case (MotionEvent.ACTION_UP): 604 float xDiff = Math.abs(e.getX() - mLastTouchX); 605 float yDiff = Math.abs(e.getY() - mLastTouchY); 606 long timeDiff = (Utils.getTimeNow() - mLastTouchTime); 607 if (xDiff < MAX_MOVEMENT_ALLOWED && yDiff < MAX_MOVEMENT_ALLOWED 608 && timeDiff < MAX_TIME_ALLOWED) { 609 if (mMakePressedTextView != null) { 610 v = mMakePressedTextView; 611 } 612 processClick(v); 613 resetValues(); 614 return true; 615 } 616 resetValues(); 617 break; 618 case (MotionEvent.ACTION_MOVE): 619 xDiff = Math.abs(e.getX() - mLastTouchX); 620 yDiff = Math.abs(e.getY() - mLastTouchY); 621 if (xDiff >= MAX_MOVEMENT_ALLOWED || yDiff >= MAX_MOVEMENT_ALLOWED) { 622 resetValues(); 623 } 624 break; 625 default: 626 resetValues(); 627 } 628 return false; 629 } 630 631 private void resetValues() { 632 mLastTouchX = -1 * MAX_MOVEMENT_ALLOWED + 1; 633 mLastTouchY = -1 * MAX_MOVEMENT_ALLOWED + 1; 634 mLastTouchTime = -1 * MAX_TIME_ALLOWED + 1; 635 if (mMakePressedTextView != null) { 636 mMakePressedTextView.setTextColor(mGrayColor); 637 } 638 } 639 640 protected abstract void processClick(View v); 641 } 642 643 /** 644 * Called by the LabelDialogFormat class after the dialog is finished. * 645 */ 646 @Override 647 public void onDialogLabelSet(TimerObj timer, String label, String tag) { 648 Fragment frag = getFragmentManager().findFragmentByTag(tag); 649 if (frag instanceof TimerFragment) { 650 ((TimerFragment) frag).setLabel(timer, label); 651 } 652 } 653 654 /** 655 * Called by the LabelDialogFormat class after the dialog is finished. * 656 */ 657 @Override 658 public void onDialogLabelSet(Alarm alarm, String label, String tag) { 659 Fragment frag = getFragmentManager().findFragmentByTag(tag); 660 if (frag instanceof AlarmClockFragment) { 661 ((AlarmClockFragment) frag).setLabel(alarm, label); 662 } 663 } 664 665 public int getSelectedTab() { 666 return mSelectedTab; 667 } 668 669 private boolean isRtl() { 670 return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == 671 View.LAYOUT_DIRECTION_RTL; 672 } 673 674 private int getRtlPosition(int position) { 675 if (isRtl()) { 676 switch (position) { 677 case TIMER_TAB_INDEX: 678 return RTL_TIMER_TAB_INDEX; 679 case CLOCK_TAB_INDEX: 680 return RTL_CLOCK_TAB_INDEX; 681 case STOPWATCH_TAB_INDEX: 682 return RTL_STOPWATCH_TAB_INDEX; 683 case ALARM_TAB_INDEX: 684 return RTL_ALARM_TAB_INDEX; 685 default: 686 break; 687 } 688 } 689 return position; 690 } 691} 692