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