11935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov/*
21935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * Copyright (C) 2011 The Android Open Source Project
31935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov *
41935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
51935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * you may not use this file except in compliance with the License.
61935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * You may obtain a copy of the License at
71935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov *
81935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
91935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov *
101935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
111935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
121935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * See the License for the specific language governing permissions and
141935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov * limitations under the License.
151935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov */
161935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
171935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganovpackage android.support.v4.view;
181935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
1930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenuItem;
2030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.util.Log;
211935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganovimport android.view.MenuItem;
221935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganovimport android.view.View;
231935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
241935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov/**
250574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * Helper for accessing features in {@link android.view.MenuItem}
260574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * introduced after API level 4 in a backwards compatible fashion.
279dcd2e58138ca4eb4b18f80b50e8979329e859d6Scott Main * <p class="note"><strong>Note:</strong> You cannot get an instance of this class. Instead,
289dcd2e58138ca4eb4b18f80b50e8979329e859d6Scott Main * it provides <em>static</em> methods that correspond to the methods in {@link
299dcd2e58138ca4eb4b18f80b50e8979329e859d6Scott Main * android.view.MenuItem}, but take a {@link android.view.MenuItem} object as an additional
309dcd2e58138ca4eb4b18f80b50e8979329e859d6Scott Main * argument.</p>
311935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov */
321935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganovpublic class MenuItemCompat {
3330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private static final String TAG = "MenuItemCompat";
341935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
351935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
361935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Never show this item as a button in an Action Bar.
371935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
381935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static final int SHOW_AS_ACTION_NEVER = 0;
391935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
401935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
411935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Show this item as a button in an Action Bar if the system
421935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * decides there is room for it.
431935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
441935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static final int SHOW_AS_ACTION_IF_ROOM = 1;
451935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
461935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
471935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Always show this item as a button in an Action Bar. Use sparingly!
481935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * If too many items are set to always show in the Action Bar it can
491935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * crowd the Action Bar and degrade the user experience on devices with
501935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * smaller screens. A good rule of thumb is to have no more than 2
511935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * items set to always show at a time.
521935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
531935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static final int SHOW_AS_ACTION_ALWAYS = 2;
541935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
551935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
561935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * When this item is in the action bar, always show it with a
571935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * text label even if it also has an icon specified.
581935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
591935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static final int SHOW_AS_ACTION_WITH_TEXT = 4;
601935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
611935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
621935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * This item's action view collapses to a normal menu item.
631935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * When expanded, the action view temporarily takes over
641935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * a larger segment of its container.
651935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
661935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8;
671935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
681935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
691935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Interface for the full API.
701935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
711935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    interface MenuVersionImpl {
7279c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes        void setShowAsAction(MenuItem item, int actionEnum);
7330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        MenuItem setActionView(MenuItem item, View view);
7430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        MenuItem setActionView(MenuItem item, int resId);
7530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        View getActionView(MenuItem item);
7630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        boolean expandActionView(MenuItem item);
7730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        boolean collapseActionView(MenuItem item);
7830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        boolean isActionViewExpanded(MenuItem item);
7930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        MenuItem setOnActionExpandListener(MenuItem item, OnActionExpandListener listener);
8030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
8130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
8230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
8330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Interface definition for a callback to be invoked when a menu item marked with {@link
8430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} is expanded or collapsed.
8530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
8630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #expandActionView(android.view.MenuItem)
8730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #collapseActionView(android.view.MenuItem)
8830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #setShowAsAction(android.view.MenuItem, int)
8930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
9030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public interface OnActionExpandListener {
9130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
9230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        /**
9330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * Called when a menu item with {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}
9430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * is expanded.
9530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         *
9630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * @param item Item that was expanded
9730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * @return true if the item should expand, false if expansion should be suppressed.
9830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         */
9930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean onMenuItemActionExpand(MenuItem item);
10030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
10130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        /**
10230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * Called when a menu item with {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}
10330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * is collapsed.
10430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         *
10530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * @param item Item that was collapsed
10630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         * @return true if the item should collapse, false if collapsing should be suppressed.
10730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell         */
10830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean onMenuItemActionCollapse(MenuItem item);
1091935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
1101935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
1111935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
1121935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Interface implementation that doesn't use anything about v4 APIs.
1131935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
1141935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    static class BaseMenuVersionImpl implements MenuVersionImpl {
1151935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        @Override
11679c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes        public void setShowAsAction(MenuItem item, int actionEnum) {
1171935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        }
1181935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
1191935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        @Override
1201935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        public MenuItem setActionView(MenuItem item, View view) {
1211935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov            return item;
1221935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        }
12330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
12430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
12530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public MenuItem setActionView(MenuItem item, int resId) {
12630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return item;
12730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
12830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
12930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
13030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public View getActionView(MenuItem item) {
13130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return null;
13230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
13330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
13430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
13530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean expandActionView(MenuItem item) {
13630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
13730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
13830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
13930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
14030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean collapseActionView(MenuItem item) {
14130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
14230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
14330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
14430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
14530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean isActionViewExpanded(MenuItem item) {
14630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
14730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
14830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
14930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
15030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public MenuItem setOnActionExpandListener(MenuItem item, OnActionExpandListener listener) {
15130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return item;
15230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
1531935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
1541935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
1551935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
1561935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Interface implementation for devices with at least v11 APIs.
1571935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
1581935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    static class HoneycombMenuVersionImpl implements MenuVersionImpl {
1591935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        @Override
16079c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes        public void setShowAsAction(MenuItem item, int actionEnum) {
1611935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov            MenuItemCompatHoneycomb.setShowAsAction(item, actionEnum);
1621935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        }
16379c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes
1641935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        @Override
1651935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        public MenuItem setActionView(MenuItem item, View view) {
1661935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov            return MenuItemCompatHoneycomb.setActionView(item, view);
1671935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        }
16830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
16930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
17030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public MenuItem setActionView(MenuItem item, int resId) {
17130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatHoneycomb.setActionView(item, resId);
17230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
17330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
17430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
17530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public View getActionView(MenuItem item) {
17630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatHoneycomb.getActionView(item);
17730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
17830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
17930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
18030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean expandActionView(MenuItem item) {
18130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
18230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
18330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
18430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
18530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean collapseActionView(MenuItem item) {
18630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
18730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
18830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
18930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
19030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean isActionViewExpanded(MenuItem item) {
19130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return false;
19230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
19330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
19430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
19530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public MenuItem setOnActionExpandListener(MenuItem item, OnActionExpandListener listener) {
19630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return item;
19730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
19830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
19930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
20030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    static class IcsMenuVersionImpl extends HoneycombMenuVersionImpl {
20130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
20230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean expandActionView(MenuItem item) {
20330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatIcs.expandActionView(item);
20430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
20530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
20630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
20730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean collapseActionView(MenuItem item) {
20830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatIcs.collapseActionView(item);
20930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
21030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
21130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
21230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public boolean isActionViewExpanded(MenuItem item) {
21330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatIcs.isActionViewExpanded(item);
21430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
21530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
21630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
21730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public MenuItem setOnActionExpandListener(MenuItem item,
21830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                final OnActionExpandListener listener) {
21930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            if (listener == null) {
22030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                return MenuItemCompatIcs.setOnActionExpandListener(item, null);
22130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            }
22230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            /*
22330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell             * MenuItemCompatIcs is a dependency of this segment of the support lib
22430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell             * but not the other way around, so we need to take an extra step here to proxy
22530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell             * to the right types.
22630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell             */
22730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return MenuItemCompatIcs.setOnActionExpandListener(item,
22830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                    new MenuItemCompatIcs.SupportActionExpandProxy() {
22930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                @Override
23030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                public boolean onMenuItemActionExpand(MenuItem item) {
23130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                    return listener.onMenuItemActionExpand(item);
23230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                }
23330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
23430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                @Override
23530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                public boolean onMenuItemActionCollapse(MenuItem item) {
23630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                    return listener.onMenuItemActionCollapse(item);
23730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                }
23830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            });
23930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
2401935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
2411935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
2421935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
2431935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Select the correct implementation to use for the current platform.
2441935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
2451935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    static final MenuVersionImpl IMPL;
2461935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    static {
24730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final int version = android.os.Build.VERSION.SDK_INT;
24830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (version >= 14) {
24930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            IMPL = new IcsMenuVersionImpl();
25030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        } else if (version >= 11) {
2511935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov            IMPL = new HoneycombMenuVersionImpl();
2521935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        } else {
2531935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov            IMPL = new BaseMenuVersionImpl();
2541935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        }
2551935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
2561935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
2571935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    // -------------------------------------------------------------------
2581935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
2591935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
26079c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * Sets how this item should display in the presence of a compatible Action Bar. If the given
26179c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * item is compatible, this will call the item's supported implementation of
26279c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * {@link MenuItem#setShowAsAction(int)}.
26379c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     *
26479c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * @param item - the item to change
26579c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * @param actionEnum - How the item should display.
2661935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
26779c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes    public static void setShowAsAction(MenuItem item, int actionEnum) {
26830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
26930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            ((SupportMenuItem) item).setShowAsAction(actionEnum);
27079c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes        } else {
27179c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes            IMPL.setShowAsAction(item, actionEnum);
27230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
2731935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
2741935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov
2751935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    /**
2761935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * Set an action view for this menu item. An action view will be displayed in place
2771935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * of an automatically generated menu item element in the UI when this item is shown
2781935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * as an action within a parent.
2791935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     *
28030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param item the item to change
2811935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * @param view View to use for presenting this item to the user.
2821935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * @return This Item so additional setters can be called.
2831935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     *
2841935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     * @see #setShowAsAction(MenuItem, int)
2851935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov     */
2861935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    public static MenuItem setActionView(MenuItem item, View view) {
28730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
28830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).setActionView(view);
28930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
2901935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov        return IMPL.setActionView(item, view);
2911935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov    }
29230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
29330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
29430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Set an action view for this menu item. An action view will be displayed in place
29530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * of an automatically generated menu item element in the UI when this item is shown
29630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * as an action within a parent.
29730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * <p>
29830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *   <strong>Note:</strong> Setting an action view overrides the action provider
29930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *           set via {@link #setActionProvider(MenuItem, ActionProvider)}.
30030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * </p>
30130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
30230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param item the item to change
30330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param resId Layout resource to use for presenting this item to the user.
30430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return This Item so additional setters can be called.
30530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
30630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #setShowAsAction(MenuItem, int)
30730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
30830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static MenuItem setActionView(MenuItem item, int resId) {
30930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
31030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).setActionView(resId);
31130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
31230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.setActionView(item, resId);
31330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
31430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
31530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
31630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Returns the currently set action view for this menu item.
31730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
31830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param item the item to query
31930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return This item's action view
32030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
32130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static View getActionView(MenuItem item) {
32230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
32330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).getActionView();
32430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
32530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.getActionView(item);
32630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
32730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
32830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
32930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Sets the {@link ActionProvider} responsible for creating an action view if
33030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * the item is placed on the action bar. The provider also provides a default
33130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * action invoked if the item is placed in the overflow menu.
33230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * <p>
33330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *   <strong>Note:</strong> Setting an action provider overrides the action view
33430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *           set via {@link #setActionView(MenuItem, View)}.
33530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * </p>
33630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
33730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param item item to change
33830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param provider The action provider.
33930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return This Item so additional setters can be called.
34030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
34130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see ActionProvider
34230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
34330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static MenuItem setActionProvider(MenuItem item, ActionProvider provider) {
34430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
34530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).setSupportActionProvider(provider);
34630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
34730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        // TODO Wrap the support ActionProvider and assign it
34830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        Log.w(TAG, "setActionProvider: item does not implement SupportMenuItem; ignoring");
34930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return item;
35030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
35130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
35230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
35330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Gets the {@link ActionProvider}.
35430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
35530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return The action provider.
35630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
35730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see ActionProvider
35830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #setActionProvider(MenuItem, ActionProvider)
35930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
36030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static ActionProvider getActionProvider(MenuItem item) {
36130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
36230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).getSupportActionProvider();
36330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
36430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
36530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        // TODO Wrap the framework ActionProvider and return it
36630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        Log.w(TAG, "getActionProvider: item does not implement SupportMenuItem; returning null");
36730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return null;
36830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
36930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
37030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
37130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Expand the action view associated with this menu item.
37230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * The menu item must have an action view set, as well as
37330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
37430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * If a listener has been set using
37530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * {@link #setOnActionExpandListener(MenuItem, OnActionExpandListener)}
37630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * it will have its {@link OnActionExpandListener#onMenuItemActionExpand(MenuItem)}
37730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * method invoked. The listener may return false from this method to prevent expanding
37830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * the action view.
37930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
38030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return true if the action view was expanded, false otherwise.
38130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
38230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static boolean expandActionView(MenuItem item) {
38330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
38430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).expandActionView();
38530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
38630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.expandActionView(item);
38730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
38830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
38930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
39030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Collapse the action view associated with this menu item. The menu item must have an action
39130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * view set, as well as the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a
39230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * listener has been set using {@link #setOnActionExpandListener(MenuItem,
39330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * android.support.v4.view.MenuItemCompat.OnActionExpandListener)}
39430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * it will have its {@link
39530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * android.support.v4.view.MenuItemCompat.OnActionExpandListener#onMenuItemActionCollapse(MenuItem)}
39630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * method invoked. The listener may return false from this method to prevent collapsing
39730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * the action view.
39830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
39930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return true if the action view was collapsed, false otherwise.
40030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
40130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static boolean collapseActionView(MenuItem item) {
40230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
40330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).collapseActionView();
40430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
40530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.collapseActionView(item);
40630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
40730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
40830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
40930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * Returns true if this menu item's action view has been expanded.
41030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
41130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return true if the item's action view is expanded, false otherwise.
41230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #expandActionView(MenuItem)
41330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #collapseActionView(MenuItem)
41430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
41530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @see android.support.v4.view.MenuItemCompat.OnActionExpandListener
41630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
41730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static boolean isActionViewExpanded(MenuItem item) {
41830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
41930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).isActionViewExpanded();
42030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
42130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.isActionViewExpanded(item);
42230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
42330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
42430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    /**
42579c1dba5b509ae3e7c867827949d8fdfd37e8f52Chris Banes     * Set an {@link OnActionExpandListener} on this menu
42630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * item to be notified when the associated action view is expanded or collapsed.
42730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * The menu item must be configured to expand or collapse its action view using the flag
42830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
42930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     *
43030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @param listener Listener that will respond to expand/collapse events
43130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     * @return This menu item instance for call chaining
43230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell     */
43330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    public static MenuItem setOnActionExpandListener(MenuItem item,
43430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            OnActionExpandListener listener) {
43530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        if (item instanceof SupportMenuItem) {
43630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return ((SupportMenuItem) item).setSupportOnActionExpandListener(listener);
43730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
43830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        return IMPL.setOnActionExpandListener(item, listener);
43930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
4401935ed3af7c6545bc38adfdc6026d87a3249222fSvetoslav Ganov}
441