am 14ca4235: Make dream setting ui fit to system screen.
* commit '14ca4235805189e33093ff728aa40a538e2e28a6':
Make dream setting ui fit to system screen.
diff --git a/res/menu/cities_menu.xml b/res/menu/cities_menu.xml
deleted file mode 100644
index a9b18f4..0000000
--- a/res/menu/cities_menu.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto">
-
- <item android:id="@+id/menu_item_search"
- android:title="@android:string/search_go"
- android:icon="@android:drawable/ic_menu_search"
- android:imeOptions="actionSearch"
- android:orderInCategory="1"
- ex:showAsAction="ifRoom"
- ex:actionViewClass="android.support.v7.widget.SearchView" />
-
- <item android:id="@+id/menu_item_sort"
- android:title="@string/menu_item_sort_by_gmt_offset"
- ex:showAsAction="never" />
-
- <item android:id="@+id/menu_item_settings"
- android:title="@string/menu_item_settings"
- android:icon="@android:drawable/ic_menu_preferences"
- ex:showAsAction="never"/>
-
- <item android:id="@+id/menu_item_help"
- android:title="@string/menu_item_help"
- android:icon="@android:drawable/ic_menu_preferences"
- ex:showAsAction="never"/>
-
-</menu>
-
-
diff --git a/res/menu/desk_clock_menu.xml b/res/menu/desk_clock_menu.xml
index b242050..8907301 100644
--- a/res/menu/desk_clock_menu.xml
+++ b/res/menu/desk_clock_menu.xml
@@ -14,8 +14,19 @@
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="@+id/menu_items">
+ <item android:id="@+id/menu_item_search"
+ android:title="@android:string/search_go"
+ android:icon="@android:drawable/ic_menu_search"
+ android:imeOptions="actionSearch"
+ android:orderInCategory="1"
+ app:showAsAction="ifRoom"
+ app:actionViewClass="android.support.v7.widget.SearchView" />
+ <item android:id="@+id/menu_item_sort"
+ android:title="@string/menu_item_sort_by_gmt_offset"
+ app:showAsAction="never" />
<item android:id="@+id/menu_item_night_mode"
android:title="@string/menu_item_night_mode"
android:icon="@android:drawable/ic_menu_preferences"/>
diff --git a/res/menu/settings_menu.xml b/res/menu/settings_menu.xml
deleted file mode 100644
index 399e393..0000000
--- a/res/menu/settings_menu.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/menu_item_help"
- android:title="@string/menu_item_help"
- android:icon="@android:drawable/ic_menu_preferences"/>
-</menu>
-
-
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2acefaf..2edb374 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -818,7 +818,6 @@
<!-- Header in the preferences settings for the section pertaining to alarms -->
<string name="alarm_settings">Alarms</string>
- <string name="desk_clock_help_url" translatable="false"></string>
<!-- Describes the running service for the stopwatch -->
<string name="stopwatch_service_desc">Stopwatch service to run the notification.</string>
<!-- Desription for the stopped stop watch -->
diff --git a/src/com/android/deskclock/AlarmClockFragment.java b/src/com/android/deskclock/AlarmClockFragment.java
index 522692d..68e9a7d 100644
--- a/src/com/android/deskclock/AlarmClockFragment.java
+++ b/src/com/android/deskclock/AlarmClockFragment.java
@@ -169,7 +169,6 @@
mAlarmUpdateHandler.hideUndoBar(false, null);
}
-
public void setLabel(Alarm alarm, String label) {
alarm.label = label;
mAlarmUpdateHandler.asyncUpdateAlarm(alarm, false, true);
diff --git a/src/com/android/deskclock/DeskClock.java b/src/com/android/deskclock/DeskClock.java
index f71d190..cf7e37d 100644
--- a/src/com/android/deskclock/DeskClock.java
+++ b/src/com/android/deskclock/DeskClock.java
@@ -18,7 +18,6 @@
import android.app.Fragment;
import android.app.FragmentManager;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -42,6 +41,11 @@
import android.widget.ImageButton;
import android.widget.ImageView;
+import com.android.deskclock.actionbarmenu.ActionBarMenuManager;
+import com.android.deskclock.actionbarmenu.MenuItemController;
+import com.android.deskclock.actionbarmenu.MenuItemControllerFactory;
+import com.android.deskclock.actionbarmenu.NightModeMenuItemController;
+import com.android.deskclock.actionbarmenu.SettingMenuItemController;
import com.android.deskclock.alarms.AlarmStateManager;
import com.android.deskclock.events.Events;
import com.android.deskclock.provider.Alarm;
@@ -72,16 +76,16 @@
private static final String KEY_SELECTED_TAB = "selected_tab";
public static final String SELECT_TAB_INTENT_EXTRA = "deskclock.select.tab";
- // Request code used when SettingsActivity is launched.
- private static final int REQUEST_CHANGE_SETTINGS = 1;
-
public static final int ALARM_TAB_INDEX = 0;
public static final int CLOCK_TAB_INDEX = 1;
public static final int TIMER_TAB_INDEX = 2;
public static final int STOPWATCH_TAB_INDEX = 3;
+ private final ActionBarMenuManager mActionBarMenuManager = new ActionBarMenuManager(this);
+ private final MenuItemController nightModeMenuItemController =
+ new NightModeMenuItemController(this);
+
private TabLayout mTabLayout;
- private Menu mMenu;
private RtlViewPager mViewPager;
private ImageView mFab;
private ImageButton mLeftButton;
@@ -178,6 +182,10 @@
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mActionBarMenuManager.addMenuItemController(new SettingMenuItemController(this))
+ .addMenuItemController(MenuItemControllerFactory.getInstance()
+ .buildMenuItemControllers(this))
+ .addMenuItemController(nightModeMenuItemController);
setVolumeControlStream(AudioManager.STREAM_ALARM);
if (icicle != null) {
@@ -249,80 +257,34 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- // We only want to show it as a menu in landscape, and only for clock/alarm fragment.
- mMenu = menu;
- // Clear the menu so that it doesn't get duplicate items in case onCreateOptionsMenu
- // was called multiple times.
- menu.clear();
- getMenuInflater().inflate(R.menu.desk_clock_menu, menu);
- // Always return true, regardless of whether we've inflated the menu, so
- // that when we switch tabs this method will get called and we can inflate the menu.
+ mActionBarMenuManager.createOptionsMenu(menu, getMenuInflater());
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- updateMenu(menu);
+ super.onPrepareOptionsMenu(menu);
+ mActionBarMenuManager.prepareShowMenu(menu);
return true;
}
- private void updateMenu(Menu menu) {
- // Hide "help" if we don't have a URI for it.
- MenuItem help = menu.findItem(R.id.menu_item_help);
- if (help != null) {
- Utils.prepareHelpMenuItem(this, help);
- }
-
- // Hide "lights out" for timer.
- MenuItem nightMode = menu.findItem(R.id.menu_item_night_mode);
- if (mTabLayout.getSelectedTabPosition() == CLOCK_TAB_INDEX) {
- nightMode.setVisible(true);
- } else {
- nightMode.setVisible(false);
- }
- }
-
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (processMenuClick(item)) {
+ if (mActionBarMenuManager.handleMenuItemClick(item)) {
return true;
}
-
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Recreate the activity if any settings have been changed
- if (requestCode == REQUEST_CHANGE_SETTINGS && resultCode == RESULT_OK) {
+ if (requestCode == SettingMenuItemController.REQUEST_CHANGE_SETTINGS
+ && resultCode == RESULT_OK) {
recreate();
}
}
- private boolean processMenuClick(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_item_settings:
- startActivityForResult(new Intent(DeskClock.this, SettingsActivity.class),
- REQUEST_CHANGE_SETTINGS);
- return true;
- case R.id.menu_item_help:
- Intent i = item.getIntent();
- if (i != null) {
- try {
- startActivity(i);
- } catch (ActivityNotFoundException e) {
- // No activity found to match the intent - ignore
- }
- }
- return true;
- case R.id.menu_item_night_mode:
- startActivity(new Intent(DeskClock.this, ScreensaverActivity.class));
- default:
- break;
- }
- return true;
- }
-
/**
* Insert the local time zone as the Home Time Zone if one is not set
*/
@@ -441,13 +403,8 @@
mTabLayout.getTabAt(position).select();
notifyPageChanged(position);
- // Only show the overflow menu for alarm and world clock.
- if (mMenu != null) {
- // Make sure the menu's been initialized.
- mMenu.setGroupVisible(R.id.menu_items, true);
- onCreateOptionsMenu(mMenu);
- }
mSelectedTab = position;
+ nightModeMenuItemController.setEnabled(mSelectedTab == CLOCK_TAB_INDEX);
if (mActivityResumed) {
switch (mSelectedTab) {
@@ -507,7 +464,6 @@
public void unregisterPageChangedListener(DeskClockFragment frag) {
mFragmentTags.remove(frag.getTag());
}
-
}
/**
diff --git a/src/com/android/deskclock/Utils.java b/src/com/android/deskclock/Utils.java
index 75e4b7a..d142dd2 100644
--- a/src/com/android/deskclock/Utils.java
+++ b/src/com/android/deskclock/Utils.java
@@ -76,18 +76,6 @@
import java.util.TimeZone;
public class Utils {
- private final static String PARAM_LANGUAGE_CODE = "hl";
-
- /**
- * Help URL query parameter key for the app version.
- */
- private final static String PARAM_VERSION = "version";
-
- /**
- * Cached version code to prevent repeated calls to the package manager.
- */
- private static String sCachedVersionCode = null;
-
// Single-char version of day name, e.g.: 'S', 'M', 'T', 'W', 'T', 'F', 'S'
private static String[] sShortWeekdays = null;
private static final String DATE_FORMAT_SHORT = "ccccc";
@@ -184,64 +172,6 @@
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
- public static void prepareHelpMenuItem(Context context, MenuItem helpMenuItem) {
- String helpUrlString = context.getResources().getString(R.string.desk_clock_help_url);
- if (TextUtils.isEmpty(helpUrlString)) {
- // The help url string is empty or null, so set the help menu item to be invisible.
- helpMenuItem.setVisible(false);
- return;
- }
- // The help url string exists, so first add in some extra query parameters. 87
- final Uri fullUri = uriWithAddedParameters(context, Uri.parse(helpUrlString));
-
- // Then, create an intent that will be fired when the user
- // selects this help menu item.
- Intent intent = new Intent(Intent.ACTION_VIEW, fullUri);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
- // Set the intent to the help menu item, show the help menu item in the overflow
- // menu, and make it visible.
- helpMenuItem.setIntent(intent);
- helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- helpMenuItem.setVisible(true);
- }
-
- /**
- * Adds two query parameters into the Uri, namely the language code and the version code
- * of the application's package as gotten via the context.
- * @return the uri with added query parameters
- */
- private static Uri uriWithAddedParameters(Context context, Uri baseUri) {
- Uri.Builder builder = baseUri.buildUpon();
-
- // Add in the preferred language
- builder.appendQueryParameter(PARAM_LANGUAGE_CODE, Locale.getDefault().toString());
-
- // Add in the package version code
- if (sCachedVersionCode == null) {
- // There is no cached version code, so try to get it from the package manager.
- try {
- // cache the version code
- PackageInfo info = context.getPackageManager().getPackageInfo(
- context.getPackageName(), 0);
- sCachedVersionCode = Integer.toString(info.versionCode);
-
- // append the version code to the uri
- builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
- } catch (NameNotFoundException e) {
- // Cannot find the package name, so don't add in the version parameter
- // This shouldn't happen.
- LogUtils.wtf("Invalid package name for context " + e);
- }
- } else {
- builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
- }
-
- // Build the full uri and return it
- return builder.build();
- }
-
public static long getTimeNow() {
return SystemClock.elapsedRealtime();
}
diff --git a/src/com/android/deskclock/actionbarmenu/AbstractMenuItemController.java b/src/com/android/deskclock/actionbarmenu/AbstractMenuItemController.java
new file mode 100644
index 0000000..047d816
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/AbstractMenuItemController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.deskclock.actionbarmenu;
+
+import android.view.Menu;
+
+/**
+ * Base of all {@link MenuItemController}. It contains basic implementation for enabling controller.
+ */
+public abstract class AbstractMenuItemController implements MenuItemController {
+ // Whether or not the controller is enabled. By default it's enabled.
+ private boolean mEnabled = true;
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ @Override
+ public void setInitialState(Menu menu) {
+ // By default, there is nothing to initialize.
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/ActionBarMenuManager.java b/src/com/android/deskclock/actionbarmenu/ActionBarMenuManager.java
new file mode 100644
index 0000000..f470e5b
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/ActionBarMenuManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.deskclock.actionbarmenu;
+
+import android.app.Activity;
+import android.util.ArrayMap;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+import com.android.deskclock.R;
+
+/**
+ * Activity scoped singleton that manages action bar menus. Each menu item is controlled by a
+ * {@link MenuItemController} instance.
+ * <p/>
+ * This class needs to be instantiated before or during activity's onCreate event.
+ */
+public final class ActionBarMenuManager {
+ // A map of all menu item controllers, keyed by menu item id.
+ private final ArrayMap<Integer, MenuItemController> mControllers;
+
+ public ActionBarMenuManager(Activity activity) {
+ mControllers = new ArrayMap<>();
+ }
+
+ /**
+ * Add one or more {@link MenuItemController} to the actionbar menu.
+ * <p/>
+ * This should be called before activity's onPrepareOptionsMenu event.
+ */
+ public ActionBarMenuManager addMenuItemController(MenuItemController... menuItemControllers) {
+ if (menuItemControllers != null) {
+ for (MenuItemController controller : menuItemControllers) {
+ mControllers.put(controller.getId(), controller);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Inflates {@link Menu} for the activity.
+ * <p/>
+ * This method should be called during activity's onCreateOptionsMenu method.
+ */
+ public void createOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (menu.size() > 0) {
+ throw new IllegalStateException("Menu has already been inflated.");
+ }
+ inflater.inflate(R.menu.desk_clock_menu, menu);
+
+ final int controllerSize = mControllers.size();
+ for (int i = 0; i < controllerSize; i++) {
+ final MenuItemController controller = mControllers.valueAt(i);
+ if (controller.isEnabled()) {
+ controller.setInitialState(menu);
+ }
+ }
+ }
+
+ /**
+ * Prepares the popup to displays all required menu items.
+ * <p/>
+ * This method should be called during activity's onPrepareOptionsMenu method.
+ */
+ public void prepareShowMenu(Menu menu) {
+ final int menuSize = menu.size();
+ for (int i = 0; i < menuSize; i++) {
+ menu.getItem(i).setVisible(false);
+ }
+ final int controllerSize = mControllers.size();
+ for (int i = 0; i < controllerSize; i++) {
+ final MenuItemController controller = mControllers.valueAt(i);
+ if (controller.isEnabled()) {
+ controller.showMenuItem(menu);
+ }
+ }
+ }
+
+ /**
+ * Handles click action for a menu item.
+ * <p/>
+ * This method should be called during activity's onOptionsItemSelected method.
+ */
+ public boolean handleMenuItemClick(MenuItem item) {
+ final int itemId = item.getItemId();
+ return mControllers.get(itemId).handleMenuItemClick(item);
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/MenuItemController.java b/src/com/android/deskclock/actionbarmenu/MenuItemController.java
new file mode 100644
index 0000000..d7cb06f
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/MenuItemController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.deskclock.actionbarmenu;
+
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Interface for handling a single menu item in action bar.
+ */
+public interface MenuItemController {
+
+ /**
+ * Sets whether or not the controller is enabled.
+ */
+ void setEnabled(boolean enabled);
+
+ /**
+ * Returns true if the controller is currently enabled.
+ */
+ boolean isEnabled();
+
+ /**
+ * Returns the menu item id that the controller is responsible for.
+ */
+ int getId();
+
+ /**
+ * Sets the initial state for the menu item.
+ */
+ void setInitialState(Menu menu);
+
+ /**
+ * Find the menu item this controller cares about, and make it visible.
+ *
+ * @param menu The menu object containing an item that controller can handle.
+ */
+ void showMenuItem(Menu menu);
+
+ /**
+ * Attempts to handle the click action.
+ *
+ * @param item The menu item being clicked.
+ * @return True if the action is handled by this controller, false otherwise.
+ */
+ boolean handleMenuItemClick(MenuItem item);
+}
diff --git a/src/com/android/deskclock/actionbarmenu/MenuItemControllerFactory.java b/src/com/android/deskclock/actionbarmenu/MenuItemControllerFactory.java
new file mode 100644
index 0000000..3598f16
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/MenuItemControllerFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.deskclock.actionbarmenu;
+
+import android.app.Activity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Factory that builds optional {@link MenuItemController} instances.
+ */
+public final class MenuItemControllerFactory {
+
+ private static final MenuItemControllerFactory INSTANCE = new MenuItemControllerFactory();
+
+ public static MenuItemControllerFactory getInstance() {
+ return INSTANCE;
+ }
+
+ private final List<MenuItemProvider> mMenuItemProviders;
+
+ private MenuItemControllerFactory() {
+ mMenuItemProviders = new ArrayList<>();
+ }
+
+ public MenuItemControllerFactory addMenuItemProvider(MenuItemProvider provider) {
+ mMenuItemProviders.add(provider);
+ return this;
+ }
+
+ public MenuItemController[] buildMenuItemControllers(Activity activity) {
+ final int providerSize = mMenuItemProviders.size();
+ final MenuItemController[] controllers = new MenuItemController[providerSize];
+ for (int i = 0; i < providerSize; i++) {
+ controllers[i] = mMenuItemProviders.get(i).provide(activity);
+ }
+ return controllers;
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/MenuItemProvider.java b/src/com/android/deskclock/actionbarmenu/MenuItemProvider.java
new file mode 100644
index 0000000..c3e460d
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/MenuItemProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.deskclock.actionbarmenu;
+
+import android.app.Activity;
+
+/**
+ * Provider for a {@link MenuItemController} instances.
+ */
+public interface MenuItemProvider {
+
+ /**
+ * provides a {@link MenuItemController} that handles menu item.
+ */
+ MenuItemController provide(Activity activity);
+}
diff --git a/src/com/android/deskclock/actionbarmenu/NavUpMenuItemController.java b/src/com/android/deskclock/actionbarmenu/NavUpMenuItemController.java
new file mode 100644
index 0000000..a2aebbf
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/NavUpMenuItemController.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.deskclock.actionbarmenu;
+
+import android.app.Activity;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * {@link MenuItemController} for handling navigation up button in actionbar. It is a special
+ * menu item because it's not inflated through menu.xml, and has its own predefined id.
+ */
+public final class NavUpMenuItemController extends AbstractMenuItemController {
+
+ private final Activity mActivity;
+
+ public NavUpMenuItemController(Activity activity) {
+ mActivity = activity;
+ }
+
+ @Override
+ public int getId() {
+ return android.R.id.home;
+ }
+
+ @Override
+ public void showMenuItem(Menu menu) {
+ // Intentionally left empty, because back button in actionbar is not shown by inflating
+ // menu layouts. It's directly controlled by actionbar.
+ }
+
+ @Override
+ public boolean handleMenuItemClick(MenuItem item) {
+ mActivity.finish();
+ return true;
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/NightModeMenuItemController.java b/src/com/android/deskclock/actionbarmenu/NightModeMenuItemController.java
new file mode 100644
index 0000000..0a98621
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/NightModeMenuItemController.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.deskclock.actionbarmenu;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.deskclock.R;
+import com.android.deskclock.ScreensaverActivity;
+
+/**
+ * {@link MenuItemController} for controlling night mode display.
+ */
+public final class NightModeMenuItemController extends AbstractMenuItemController {
+
+ private static final int NIGHT_MODE_MENU_RES_ID = R.id.menu_item_night_mode;
+
+ private final Context mContext;
+
+ public NightModeMenuItemController(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public int getId() {
+ return NIGHT_MODE_MENU_RES_ID;
+ }
+
+ @Override
+ public void showMenuItem(Menu menu) {
+ menu.findItem(NIGHT_MODE_MENU_RES_ID).setVisible(true);
+ }
+
+ @Override
+ public boolean handleMenuItemClick(MenuItem item) {
+ mContext.startActivity(new Intent(mContext, ScreensaverActivity.class));
+ return true;
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/SearchMenuItemController.java b/src/com/android/deskclock/actionbarmenu/SearchMenuItemController.java
new file mode 100644
index 0000000..fbba78d
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/SearchMenuItemController.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.deskclock.actionbarmenu;
+
+import android.os.Bundle;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.SearchView;
+import android.support.v7.widget.SearchView.OnQueryTextListener;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.deskclock.R;
+
+/**
+ * {@link MenuItemController} for search menu.
+ */
+public final class SearchMenuItemController extends AbstractMenuItemController {
+
+ private static final String KEY_SEARCH_QUERY = "search_query";
+ private static final String KEY_SEARCH_MODE = "search_mode";
+ private static final int SEARCH_MENU_RES_ID = R.id.menu_item_search;
+ private final SearchView.OnQueryTextListener mQueryListener;
+ private final SearchModeChangeListener mSearchModeChangeListener;
+ private String mQuery = "";
+ private boolean mSearchMode;
+
+ public SearchMenuItemController(OnQueryTextListener queryListener, Bundle savedState) {
+ mSearchModeChangeListener = new SearchModeChangeListener();
+ mQueryListener = queryListener;
+ if (savedState != null) {
+ mSearchMode = savedState.getBoolean(KEY_SEARCH_MODE, false);
+ mQuery = savedState.getString(KEY_SEARCH_QUERY, "");
+ }
+ }
+
+ public void saveInstance(Bundle outState) {
+ outState.putString(KEY_SEARCH_QUERY, mQuery);
+ outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
+ }
+
+ @Override
+ public int getId() {
+ return SEARCH_MENU_RES_ID;
+ }
+
+ @Override
+ public void setInitialState(Menu menu) {
+ super.setInitialState(menu);
+ final MenuItem search = menu.findItem(SEARCH_MENU_RES_ID);
+ final SearchView searchView = (SearchView) MenuItemCompat.getActionView(search);
+ searchView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ searchView.setQuery(mQuery, false);
+ searchView.setOnCloseListener(mSearchModeChangeListener);
+ searchView.setOnSearchClickListener(mSearchModeChangeListener);
+ searchView.setOnQueryTextListener(mQueryListener);
+ if (mSearchMode) {
+ searchView.requestFocus();
+ searchView.setIconified(false);
+ }
+ }
+
+ @Override
+ public void showMenuItem(Menu menu) {
+ menu.findItem(SEARCH_MENU_RES_ID).setVisible(true);
+ }
+
+ @Override
+ public boolean handleMenuItemClick(MenuItem item) {
+ // The search view is handled by {@link #mSearchListener}. Skip handling here.
+ return false;
+ }
+
+ public String getQueryText() {
+ return mQuery;
+ }
+
+ public void setQueryText(String query) {
+ mQuery = query;
+ }
+
+ /**
+ * Listener for user actions on search view.
+ */
+ private final class SearchModeChangeListener implements View.OnClickListener,
+ SearchView.OnCloseListener {
+ @Override
+ public void onClick(View v) {
+ mSearchMode = true;
+ }
+
+ @Override
+ public boolean onClose() {
+ mSearchMode = false;
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/deskclock/actionbarmenu/SettingMenuItemController.java b/src/com/android/deskclock/actionbarmenu/SettingMenuItemController.java
new file mode 100644
index 0000000..a984451
--- /dev/null
+++ b/src/com/android/deskclock/actionbarmenu/SettingMenuItemController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.deskclock.actionbarmenu;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.deskclock.R;
+import com.android.deskclock.settings.SettingsActivity;
+
+/**
+ * {@link MenuItemController} for setting menu.
+ */
+public final class SettingMenuItemController extends AbstractMenuItemController {
+
+ public static final int REQUEST_CHANGE_SETTINGS = 1;
+
+ private static final int SETTING_MENU_RES_ID = R.id.menu_item_settings;
+ private final Activity mActivity;
+
+ public SettingMenuItemController(Activity activity) {
+ mActivity = activity;
+ }
+
+ @Override
+ public int getId() {
+ return SETTING_MENU_RES_ID;
+ }
+
+ @Override
+ public void showMenuItem(Menu menu) {
+ menu.findItem(SETTING_MENU_RES_ID).setVisible(true);
+ }
+
+ @Override
+ public boolean handleMenuItemClick(MenuItem item) {
+ Intent settingIntent = new Intent(mActivity, SettingsActivity.class);
+ mActivity.startActivityForResult(settingIntent, REQUEST_CHANGE_SETTINGS);
+ return true;
+ }
+}
diff --git a/src/com/android/deskclock/settings/SettingsActivity.java b/src/com/android/deskclock/settings/SettingsActivity.java
index 777fe72..6e3266a 100644
--- a/src/com/android/deskclock/settings/SettingsActivity.java
+++ b/src/com/android/deskclock/settings/SettingsActivity.java
@@ -36,6 +36,9 @@
import com.android.deskclock.LogUtils;
import com.android.deskclock.R;
import com.android.deskclock.Utils;
+import com.android.deskclock.actionbarmenu.ActionBarMenuManager;
+import com.android.deskclock.actionbarmenu.MenuItemControllerFactory;
+import com.android.deskclock.actionbarmenu.NavUpMenuItemController;
import com.android.deskclock.data.DataModel;
import java.util.ArrayList;
@@ -68,36 +71,38 @@
public static final String VOLUME_BEHAVIOR_SNOOZE = "1";
public static final String VOLUME_BEHAVIOR_DISMISS = "2";
+ private final ActionBarMenuManager mActionBarMenuManager = new ActionBarMenuManager(this);
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_ALARM);
setContentView(R.layout.settings);
+ mActionBarMenuManager.addMenuItemController(new NavUpMenuItemController(this))
+ .addMenuItemController(MenuItemControllerFactory.getInstance()
+ .buildMenuItemControllers(this));
}
@Override
- public boolean onOptionsItemSelected (MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- default:
- break;
+ public boolean onCreateOptionsMenu(Menu menu) {
+ mActionBarMenuManager.createOptionsMenu(menu, getMenuInflater());
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ mActionBarMenuManager.prepareShowMenu(menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mActionBarMenuManager.handleMenuItemClick(item)) {
+ return true;
}
return super.onOptionsItemSelected(item);
}
- @Override
- public boolean onCreateOptionsMenu (Menu menu) {
- getMenuInflater().inflate(R.menu.settings_menu, menu);
- MenuItem help = menu.findItem(R.id.menu_item_help);
- if (help != null) {
- Utils.prepareHelpMenuItem(this, help);
- }
- return super.onCreateOptionsMenu(menu);
- }
-
-
public static class PrefsFragment extends PreferenceFragment
implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
@@ -150,7 +155,7 @@
break;
case KEY_WEEK_START:
final ListPreference weekStartPref = (ListPreference)
- findPreference(KEY_WEEK_START);
+ findPreference(KEY_WEEK_START);
idx = weekStartPref.findIndexOfValue((String) newValue);
weekStartPref.setSummary(weekStartPref.getEntries()[idx]);
break;
diff --git a/src/com/android/deskclock/timer/TimerFragment.java b/src/com/android/deskclock/timer/TimerFragment.java
index 10a017f..6bbd6e9 100644
--- a/src/com/android/deskclock/timer/TimerFragment.java
+++ b/src/com/android/deskclock/timer/TimerFragment.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.deskclock.timer;
import android.animation.Animator;
diff --git a/src/com/android/deskclock/worldclock/CitySelectionActivity.java b/src/com/android/deskclock/worldclock/CitySelectionActivity.java
index 726cf45..2af0ce0 100644
--- a/src/com/android/deskclock/worldclock/CitySelectionActivity.java
+++ b/src/com/android/deskclock/worldclock/CitySelectionActivity.java
@@ -16,12 +16,9 @@
package com.android.deskclock.worldclock;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
-import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -32,7 +29,6 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
@@ -43,9 +39,14 @@
import com.android.deskclock.BaseActivity;
import com.android.deskclock.R;
import com.android.deskclock.Utils;
+import com.android.deskclock.actionbarmenu.AbstractMenuItemController;
+import com.android.deskclock.actionbarmenu.ActionBarMenuManager;
+import com.android.deskclock.actionbarmenu.MenuItemControllerFactory;
+import com.android.deskclock.actionbarmenu.NavUpMenuItemController;
+import com.android.deskclock.actionbarmenu.SearchMenuItemController;
+import com.android.deskclock.actionbarmenu.SettingMenuItemController;
import com.android.deskclock.data.City;
import com.android.deskclock.data.DataModel;
-import com.android.deskclock.settings.SettingsActivity;
import java.util.ArrayList;
import java.util.Calendar;
@@ -72,35 +73,45 @@
*/
public final class CitySelectionActivity extends BaseActivity {
- /** Key in the state bundle by which the user's query is stored. */
- private static final String KEY_SEARCH_QUERY = "search_query";
-
- /** Key in the state bundle by which the user's search mode is stored. */
- private static final String KEY_SEARCH_MODE = "search_mode";
-
- /** {@code true} when the user has entered search mode. */
- private boolean mSearchMode = false;
-
/** The list of all selected and unselected cities, indexed and possibly filtered. */
private ListView mCitiesList;
/** The adapter that presents all of the selected and unselected cities. */
private CityAdapter mCitiesAdapter;
+ /** Manages all action bar menu display and click handling. */
+ private final ActionBarMenuManager mActionBarMenuManager = new ActionBarMenuManager(this);
+
+ /** Menu item controller for search view. */
+ private SearchMenuItemController mSearchMenuItemController;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_ALARM);
- mCitiesAdapter = new CityAdapter(this);
-
- // Restore state information if it exists.
- if (savedInstanceState != null) {
- mSearchMode = savedInstanceState.getBoolean(KEY_SEARCH_MODE);
- mCitiesAdapter.setQueryText(savedInstanceState.getString(KEY_SEARCH_QUERY));
- }
-
setContentView(R.layout.cities_activity);
+ mSearchMenuItemController =
+ new SearchMenuItemController(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String query) {
+ mCitiesAdapter.filter(query);
+ updateFastScrolling();
+ return true;
+ }
+ }, savedInstanceState);
+ mCitiesAdapter = new CityAdapter(this, mSearchMenuItemController);
+ mActionBarMenuManager.addMenuItemController(new NavUpMenuItemController(this))
+ .addMenuItemController(mSearchMenuItemController)
+ .addMenuItemController(new SortOrderMenuItemController())
+ .addMenuItemController(new SettingMenuItemController(this))
+ .addMenuItemController(MenuItemControllerFactory.getInstance()
+ .buildMenuItemControllers(this));
mCitiesList = (ListView) findViewById(R.id.cities_list);
mCitiesList.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
mCitiesList.setAdapter(mCitiesAdapter);
@@ -111,8 +122,7 @@
@Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
- bundle.putString(KEY_SEARCH_QUERY, mCitiesAdapter.getQueryText());
- bundle.putBoolean(KEY_SEARCH_MODE, mSearchMode);
+ mSearchMenuItemController.saveInstance(bundle);
}
@Override
@@ -133,70 +143,20 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.cities_menu, menu);
-
- final MenuItem help = menu.findItem(R.id.menu_item_help);
- Utils.prepareHelpMenuItem(this, help);
-
- final SearchListener searchListener = new SearchListener();
- final MenuItem search = menu.findItem(R.id.menu_item_search);
- final SearchView searchView = (SearchView) MenuItemCompat.getActionView(search);
- searchView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
- searchView.setQuery(mCitiesAdapter.getQueryText(), false);
- searchView.setOnCloseListener(searchListener);
- searchView.setOnQueryTextListener(searchListener);
- searchView.setOnSearchClickListener(searchListener);
-
- if (mSearchMode) {
- searchView.requestFocus();
- searchView.setIconified(false);
- }
-
- return super.onCreateOptionsMenu(menu);
+ mActionBarMenuManager.createOptionsMenu(menu, getMenuInflater());
+ return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- final MenuItem sort = menu.findItem(R.id.menu_item_sort);
-
- // Adjust the title of the sort menu item to the opposite of the current sort order.
- if (DataModel.getDataModel().getCitySort() == DataModel.CitySort.NAME) {
- sort.setTitle(getString(R.string.menu_item_sort_by_gmt_offset));
- } else {
- sort.setTitle(getString(R.string.menu_item_sort_by_name));
- }
- return super.onPrepareOptionsMenu(menu);
+ mActionBarMenuManager.prepareShowMenu(menu);
+ return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- case R.id.menu_item_sort:
- // Save the new sort order.
- DataModel.getDataModel().toggleCitySort();
-
- // Section headers are influenced by sort order and must be cleared.
- mCitiesAdapter.clearSectionHeaders();
-
- // Honor the new sort order in the adapter.
- mCitiesAdapter.filter(mCitiesAdapter.getQueryText());
- return true;
- case R.id.menu_item_settings:
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- case R.id.menu_item_help:
- final Intent i = item.getIntent();
- if (i != null) {
- try {
- startActivity(i);
- } catch (ActivityNotFoundException e) {
- // No activity found to match the intent - ignore
- }
- }
- return true;
+ if (mActionBarMenuManager.handleMenuItemClick(item)) {
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -211,35 +171,6 @@
}
/**
- * Listeners that update the UI state in response to changes in the search component.
- */
- private final class SearchListener implements View.OnClickListener, SearchView.OnCloseListener,
- SearchView.OnQueryTextListener {
- @Override
- public void onClick(View v) {
- mSearchMode = true;
- }
-
- @Override
- public boolean onClose() {
- mSearchMode = false;
- return false;
- }
-
- @Override
- public boolean onQueryTextChange(String queryText) {
- mCitiesAdapter.filter(queryText);
- updateFastScrolling();
- return true;
- }
-
- @Override
- public boolean onQueryTextSubmit(String s) {
- return false;
- }
- }
-
- /**
* This adapter presents data in 2 possible modes. If selected cities exist the format is:
*
* <pre>
@@ -306,11 +237,12 @@
/** The corresponding location of each precomputed section header. */
private Integer[] mSectionHeaderPositions;
- /** The query text currently filtering the cities. */
- private String mQueryText = "";
+ /** Menu item controller for search. Search query is maintained here. */
+ private final SearchMenuItemController mSearchMenuItemController;
- public CityAdapter(Context context) {
+ public CityAdapter(Context context, SearchMenuItemController searchMenuItemController) {
mContext = context;
+ mSearchMenuItemController = searchMenuItemController;
mInflater = LayoutInflater.from(context);
mCalendar = Calendar.getInstance();
@@ -522,15 +454,15 @@
clearSectionHeaders();
// Recompute filtered cities.
- filter(getQueryText());
+ filter(mSearchMenuItemController.getQueryText());
}
/**
* Filter the cities using the given {@code queryText}.
*/
private void filter(String queryText) {
- setQueryText(queryText);
- final String query = mQueryText.trim().toUpperCase();
+ mSearchMenuItemController.setQueryText(queryText);
+ final String query = queryText.trim().toUpperCase();
// Compute the filtered list of cities.
final List<City> filteredCities;
@@ -551,9 +483,10 @@
notifyDataSetChanged();
}
- private String getQueryText() { return mQueryText; }
- private void setQueryText(String queryText) { mQueryText = queryText; }
- private boolean isFiltering() { return !TextUtils.isEmpty(mQueryText.trim()); }
+ private boolean isFiltering() {
+ return !TextUtils.isEmpty(mSearchMenuItemController.getQueryText().trim());
+ }
+
private Collection<City> getSelectedCities() { return mUserSelectedCities; }
private boolean hasHeader() { return !isFiltering() && mOriginalUserSelectionCount > 0; }
@@ -622,4 +555,40 @@
}
}
}
-}
\ No newline at end of file
+
+ private final class SortOrderMenuItemController extends AbstractMenuItemController {
+
+ private static final int SORT_MENU_RES_ID = R.id.menu_item_sort;
+
+ @Override
+ public int getId() {
+ return SORT_MENU_RES_ID;
+ }
+
+ @Override
+ public void showMenuItem(Menu menu) {
+ final MenuItem sortMenuItem = menu.findItem(SORT_MENU_RES_ID);
+ final String title;
+ if (DataModel.getDataModel().getCitySort() == DataModel.CitySort.NAME) {
+ title = getString(R.string.menu_item_sort_by_gmt_offset);
+ } else {
+ title = getString(R.string.menu_item_sort_by_name);
+ }
+ sortMenuItem.setTitle(title);
+ sortMenuItem.setVisible(true);
+ }
+
+ @Override
+ public boolean handleMenuItemClick(MenuItem item) {
+ // Save the new sort order.
+ DataModel.getDataModel().toggleCitySort();
+
+ // Section headers are influenced by sort order and must be cleared.
+ mCitiesAdapter.clearSectionHeaders();
+
+ // Honor the new sort order in the adapter.
+ mCitiesAdapter.filter(mSearchMenuItemController.getQueryText());
+ return true;
+ }
+ }
+}