create changelog entry
[debian/openrocket] / android-libraries / ActionBarSherlock / src / com / actionbarsherlock / ActionBarSherlock.java
1 package com.actionbarsherlock;\r
2 \r
3 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;\r
4 import java.lang.annotation.ElementType;\r
5 import java.lang.annotation.Retention;\r
6 import java.lang.annotation.RetentionPolicy;\r
7 import java.lang.annotation.Target;\r
8 import java.lang.reflect.Constructor;\r
9 import java.lang.reflect.InvocationTargetException;\r
10 import java.util.HashMap;\r
11 import java.util.Iterator;\r
12 import android.app.Activity;\r
13 import android.content.Context;\r
14 import android.content.res.Configuration;\r
15 import android.os.Build;\r
16 import android.os.Bundle;\r
17 import android.util.DisplayMetrics;\r
18 import android.util.Log;\r
19 import android.view.KeyEvent;\r
20 import android.view.View;\r
21 import android.view.ViewGroup;\r
22 import android.view.Window;\r
23 import com.actionbarsherlock.app.ActionBar;\r
24 import com.actionbarsherlock.internal.ActionBarSherlockCompat;\r
25 import com.actionbarsherlock.internal.ActionBarSherlockNative;\r
26 import com.actionbarsherlock.view.ActionMode;\r
27 import com.actionbarsherlock.view.Menu;\r
28 import com.actionbarsherlock.view.MenuInflater;\r
29 import com.actionbarsherlock.view.MenuItem;\r
30 \r
31 /**\r
32  * <p>Helper for implementing the action bar design pattern across all versions\r
33  * of Android.</p>\r
34  *\r
35  * <p>This class will manage interaction with a custom action bar based on the\r
36  * Android 4.0 source code. The exposed API mirrors that of its native\r
37  * counterpart and you should refer to its documentation for instruction.</p>\r
38  *\r
39  * @author Jake Wharton <jakewharton@gmail.com>\r
40  */\r
41 public abstract class ActionBarSherlock {\r
42     protected static final String TAG = "ActionBarSherlock";\r
43     protected static final boolean DEBUG = false;\r
44 \r
45     private static final Class<?>[] CONSTRUCTOR_ARGS = new Class[] { Activity.class, int.class };\r
46     private static final HashMap<Implementation, Class<? extends ActionBarSherlock>> IMPLEMENTATIONS =\r
47             new HashMap<Implementation, Class<? extends ActionBarSherlock>>();\r
48 \r
49     static {\r
50         //Register our two built-in implementations\r
51         registerImplementation(ActionBarSherlockCompat.class);\r
52         registerImplementation(ActionBarSherlockNative.class);\r
53     }\r
54 \r
55 \r
56     /**\r
57      * <p>Denotes an implementation of ActionBarSherlock which provides an\r
58      * action bar-enhanced experience.</p>\r
59      */\r
60     @Target(ElementType.TYPE)\r
61     @Retention(RetentionPolicy.RUNTIME)\r
62     public @interface Implementation {\r
63         static final int DEFAULT_API = -1;\r
64         static final int DEFAULT_DPI = -1;\r
65 \r
66         int api() default DEFAULT_API;\r
67         int dpi() default DEFAULT_DPI;\r
68     }\r
69 \r
70 \r
71     /** Activity interface for menu creation callback. */\r
72     public interface OnCreatePanelMenuListener {\r
73         public boolean onCreatePanelMenu(int featureId, Menu menu);\r
74     }\r
75     /** Activity interface for menu creation callback. */\r
76     public interface OnCreateOptionsMenuListener {\r
77         public boolean onCreateOptionsMenu(Menu menu);\r
78     }\r
79     /** Activity interface for menu item selection callback. */\r
80     public interface OnMenuItemSelectedListener {\r
81         public boolean onMenuItemSelected(int featureId, MenuItem item);\r
82     }\r
83     /** Activity interface for menu item selection callback. */\r
84     public interface OnOptionsItemSelectedListener {\r
85         public boolean onOptionsItemSelected(MenuItem item);\r
86     }\r
87     /** Activity interface for menu preparation callback. */\r
88     public interface OnPreparePanelListener {\r
89         public boolean onPreparePanel(int featureId, View view, Menu menu);\r
90     }\r
91     /** Activity interface for menu preparation callback. */\r
92     public interface OnPrepareOptionsMenuListener {\r
93         public boolean onPrepareOptionsMenu(Menu menu);\r
94     }\r
95     /** Activity interface for action mode finished callback. */\r
96     public interface OnActionModeFinishedListener {\r
97         public void onActionModeFinished(ActionMode mode);\r
98     }\r
99     /** Activity interface for action mode started callback. */\r
100     public interface OnActionModeStartedListener {\r
101         public void onActionModeStarted(ActionMode mode);\r
102     }\r
103 \r
104 \r
105     /**\r
106      * If set, the logic in these classes will assume that an {@link Activity}\r
107      * is dispatching all of the required events to the class. This flag should\r
108      * only be used internally or if you are creating your own base activity\r
109      * modeled after one of the included types (e.g., {@code SherlockActivity}).\r
110      */\r
111     public static final int FLAG_DELEGATE = 1;\r
112 \r
113 \r
114     /**\r
115      * Register an ActionBarSherlock implementation.\r
116      *\r
117      * @param implementationClass Target implementation class which extends\r
118      * {@link ActionBarSherlock}. This class must also be annotated with\r
119      * {@link Implementation}.\r
120      */\r
121     public static void registerImplementation(Class<? extends ActionBarSherlock> implementationClass) {\r
122         if (!implementationClass.isAnnotationPresent(Implementation.class)) {\r
123             throw new IllegalArgumentException("Class " + implementationClass.getSimpleName() + " is not annotated with @Implementation");\r
124         } else if (IMPLEMENTATIONS.containsValue(implementationClass)) {\r
125             if (DEBUG) Log.w(TAG, "Class " + implementationClass.getSimpleName() + " already registered");\r
126             return;\r
127         }\r
128 \r
129         Implementation impl = implementationClass.getAnnotation(Implementation.class);\r
130         if (DEBUG) Log.i(TAG, "Registering " + implementationClass.getSimpleName() + " with qualifier " + impl);\r
131         IMPLEMENTATIONS.put(impl, implementationClass);\r
132     }\r
133 \r
134     /**\r
135      * Unregister an ActionBarSherlock implementation. <strong>This should be\r
136      * considered very volatile and you should only use it if you know what\r
137      * you are doing.</strong> You have been warned.\r
138      *\r
139      * @param implementationClass Target implementation class.\r
140      * @return Boolean indicating whether the class was removed.\r
141      */\r
142     public static boolean unregisterImplementation(Class<? extends ActionBarSherlock> implementationClass) {\r
143         return IMPLEMENTATIONS.values().remove(implementationClass);\r
144     }\r
145 \r
146     /**\r
147      * Wrap an activity with an action bar abstraction which will enable the\r
148      * use of a custom implementation on platforms where a native version does\r
149      * not exist.\r
150      *\r
151      * @param activity Activity to wrap.\r
152      * @return Instance to interact with the action bar.\r
153      */\r
154     public static ActionBarSherlock wrap(Activity activity) {\r
155         return wrap(activity, 0);\r
156     }\r
157 \r
158     /**\r
159      * Wrap an activity with an action bar abstraction which will enable the\r
160      * use of a custom implementation on platforms where a native version does\r
161      * not exist.\r
162      *\r
163      * @param activity Owning activity.\r
164      * @param flags Option flags to control behavior.\r
165      * @return Instance to interact with the action bar.\r
166      */\r
167     public static ActionBarSherlock wrap(Activity activity, int flags) {\r
168         //Create a local implementation map we can modify\r
169         HashMap<Implementation, Class<? extends ActionBarSherlock>> impls =\r
170                 new HashMap<Implementation, Class<? extends ActionBarSherlock>>(IMPLEMENTATIONS);\r
171         boolean hasQualfier;\r
172 \r
173         /* DPI FILTERING */\r
174         hasQualfier = false;\r
175         for (Implementation key : impls.keySet()) {\r
176             //Only honor TVDPI as a specific qualifier\r
177             if (key.dpi() == DisplayMetrics.DENSITY_TV) {\r
178                 hasQualfier = true;\r
179                 break;\r
180             }\r
181         }\r
182         if (hasQualfier) {\r
183             final boolean isTvDpi = activity.getResources().getDisplayMetrics().densityDpi == DisplayMetrics.DENSITY_TV;\r
184             for (Iterator<Implementation> keys = impls.keySet().iterator(); keys.hasNext(); ) {\r
185                 int keyDpi = keys.next().dpi();\r
186                 if ((isTvDpi && keyDpi != DisplayMetrics.DENSITY_TV)\r
187                         || (!isTvDpi && keyDpi == DisplayMetrics.DENSITY_TV)) {\r
188                     keys.remove();\r
189                 }\r
190             }\r
191         }\r
192 \r
193         /* API FILTERING */\r
194         hasQualfier = false;\r
195         for (Implementation key : impls.keySet()) {\r
196             if (key.api() != Implementation.DEFAULT_API) {\r
197                 hasQualfier = true;\r
198                 break;\r
199             }\r
200         }\r
201         if (hasQualfier) {\r
202             final int runtimeApi = Build.VERSION.SDK_INT;\r
203             int bestApi = 0;\r
204             for (Iterator<Implementation> keys = impls.keySet().iterator(); keys.hasNext(); ) {\r
205                 int keyApi = keys.next().api();\r
206                 if (keyApi > runtimeApi) {\r
207                     keys.remove();\r
208                 } else if (keyApi > bestApi) {\r
209                     bestApi = keyApi;\r
210                 }\r
211             }\r
212             for (Iterator<Implementation> keys = impls.keySet().iterator(); keys.hasNext(); ) {\r
213                 if (keys.next().api() != bestApi) {\r
214                     keys.remove();\r
215                 }\r
216             }\r
217         }\r
218 \r
219         if (impls.size() > 1) {\r
220             throw new IllegalStateException("More than one implementation matches configuration.");\r
221         }\r
222         if (impls.isEmpty()) {\r
223             throw new IllegalStateException("No implementations match configuration.");\r
224         }\r
225         Class<? extends ActionBarSherlock> impl = impls.values().iterator().next();\r
226         if (DEBUG) Log.i(TAG, "Using implementation: " + impl.getSimpleName());\r
227 \r
228         try {\r
229             Constructor<? extends ActionBarSherlock> ctor = impl.getConstructor(CONSTRUCTOR_ARGS);\r
230             return ctor.newInstance(activity, flags);\r
231         } catch (NoSuchMethodException e) {\r
232             throw new RuntimeException(e);\r
233         } catch (IllegalArgumentException e) {\r
234             throw new RuntimeException(e);\r
235         } catch (InstantiationException e) {\r
236             throw new RuntimeException(e);\r
237         } catch (IllegalAccessException e) {\r
238             throw new RuntimeException(e);\r
239         } catch (InvocationTargetException e) {\r
240             throw new RuntimeException(e);\r
241         }\r
242     }\r
243 \r
244 \r
245     /** Activity which is displaying the action bar. Also used for context. */\r
246     protected final Activity mActivity;\r
247     /** Whether delegating actions for the activity or managing ourselves. */\r
248     protected final boolean mIsDelegate;\r
249 \r
250     /** Reference to our custom menu inflater which supports action items. */\r
251     protected MenuInflater mMenuInflater;\r
252 \r
253 \r
254 \r
255     protected ActionBarSherlock(Activity activity, int flags) {\r
256         if (DEBUG) Log.d(TAG, "[<ctor>] activity: " + activity + ", flags: " + flags);\r
257 \r
258         mActivity = activity;\r
259         mIsDelegate = (flags & FLAG_DELEGATE) != 0;\r
260     }\r
261 \r
262 \r
263     /**\r
264      * Get the current action bar instance.\r
265      *\r
266      * @return Action bar instance.\r
267      */\r
268     public abstract ActionBar getActionBar();\r
269 \r
270 \r
271     ///////////////////////////////////////////////////////////////////////////\r
272     // Lifecycle and interaction callbacks when delegating\r
273     ///////////////////////////////////////////////////////////////////////////\r
274 \r
275     /**\r
276      * Notify action bar of a configuration change event. Should be dispatched\r
277      * after the call to the superclass implementation.\r
278      *\r
279      * <blockquote><pre>\r
280      * @Override\r
281      * public void onConfigurationChanged(Configuration newConfig) {\r
282      *     super.onConfigurationChanged(newConfig);\r
283      *     mSherlock.dispatchConfigurationChanged(newConfig);\r
284      * }\r
285      * </pre></blockquote>\r
286      *\r
287      * @param newConfig The new device configuration.\r
288      */\r
289     public void dispatchConfigurationChanged(Configuration newConfig) {}\r
290 \r
291     /**\r
292      * Notify the action bar that the activity has finished its resuming. This\r
293      * should be dispatched after the call to the superclass implementation.\r
294      *\r
295      * <blockquote><pre>\r
296      * @Override\r
297      * protected void onPostResume() {\r
298      *     super.onPostResume();\r
299      *     mSherlock.dispatchPostResume();\r
300      * }\r
301      * </pre></blockquote>\r
302      */\r
303     public void dispatchPostResume() {}\r
304 \r
305     /**\r
306      * Notify the action bar that the activity is pausing. This should be\r
307      * dispatched before the call to the superclass implementation.\r
308      *\r
309      * <blockquote><pre>\r
310      * @Override\r
311      * protected void onPause() {\r
312      *     mSherlock.dispatchPause();\r
313      *     super.onPause();\r
314      * }\r
315      * </pre></blockquote>\r
316      */\r
317     public void dispatchPause() {}\r
318 \r
319     /**\r
320      * Notify the action bar that the activity is stopping. This should be\r
321      * called before the superclass implementation.\r
322      *\r
323      * <blockquote><p>\r
324      * @Override\r
325      * protected void onStop() {\r
326      *     mSherlock.dispatchStop();\r
327      *     super.onStop();\r
328      * }\r
329      * </p></blockquote>\r
330      */\r
331     public void dispatchStop() {}\r
332 \r
333     /**\r
334      * Indicate that the menu should be recreated by calling\r
335      * {@link OnCreateOptionsMenuListener#onCreateOptionsMenu(com.actionbarsherlock.view.Menu)}.\r
336      */\r
337     public abstract void dispatchInvalidateOptionsMenu();\r
338 \r
339     /**\r
340      * Notify the action bar that it should display its overflow menu if it is\r
341      * appropriate for the device. The implementation should conditionally\r
342      * call the superclass method only if this method returns {@code false}.\r
343      *\r
344      * <blockquote><p>\r
345      * @Override\r
346      * public void openOptionsMenu() {\r
347      *     if (!mSherlock.dispatchOpenOptionsMenu()) {\r
348      *         super.openOptionsMenu();\r
349      *     }\r
350      * }\r
351      * </p></blockquote>\r
352      *\r
353      * @return {@code true} if the opening of the menu was handled internally.\r
354      */\r
355     public boolean dispatchOpenOptionsMenu() {\r
356         return false;\r
357     }\r
358 \r
359     /**\r
360      * Notify the action bar that it should close its overflow menu if it is\r
361      * appropriate for the device. This implementation should conditionally\r
362      * call the superclass method only if this method returns {@code false}.\r
363      *\r
364      * <blockquote><pre>\r
365      * @Override\r
366      * public void closeOptionsMenu() {\r
367      *     if (!mSherlock.dispatchCloseOptionsMenu()) {\r
368      *         super.closeOptionsMenu();\r
369      *     }\r
370      * }\r
371      * </pre></blockquote>\r
372      *\r
373      * @return {@code true} if the closing of the menu was handled internally.\r
374      */\r
375     public boolean dispatchCloseOptionsMenu() {\r
376         return false;\r
377     }\r
378 \r
379     /**\r
380      * Notify the class that the activity has finished its creation. This\r
381      * should be called after the superclass implementation.\r
382      *\r
383      * <blockquote><pre>\r
384      * @Override\r
385      * protected void onPostCreate(Bundle savedInstanceState) {\r
386      *     mSherlock.dispatchPostCreate(savedInstanceState);\r
387      *     super.onPostCreate(savedInstanceState);\r
388      * }\r
389      * </pre></blockquote>\r
390      *\r
391      * @param savedInstanceState If the activity is being re-initialized after\r
392      *                           previously being shut down then this Bundle\r
393      *                           contains the data it most recently supplied in\r
394      *                           {@link Activity#}onSaveInstanceState(Bundle)}.\r
395      *                           <strong>Note: Otherwise it is null.</strong>\r
396      */\r
397     public void dispatchPostCreate(Bundle savedInstanceState) {}\r
398 \r
399     /**\r
400      * Notify the action bar that the title has changed and the action bar\r
401      * should be updated to reflect the change. This should be called before\r
402      * the superclass implementation.\r
403      *\r
404      * <blockquote><pre>\r
405      *  @Override\r
406      *  protected void onTitleChanged(CharSequence title, int color) {\r
407      *      mSherlock.dispatchTitleChanged(title, color);\r
408      *      super.onTitleChanged(title, color);\r
409      *  }\r
410      * </pre></blockquote>\r
411      *\r
412      * @param title New activity title.\r
413      * @param color New activity color.\r
414      */\r
415     public void dispatchTitleChanged(CharSequence title, int color) {}\r
416 \r
417     /**\r
418      * Notify the action bar the user has created a key event. This is used to\r
419      * toggle the display of the overflow action item with the menu key and to\r
420      * close the action mode or expanded action item with the back key.\r
421      *\r
422      * <blockquote><pre>\r
423      * @Override\r
424      * public boolean dispatchKeyEvent(KeyEvent event) {\r
425      *     if (mSherlock.dispatchKeyEvent(event)) {\r
426      *         return true;\r
427      *     }\r
428      *     return super.dispatchKeyEvent(event);\r
429      * }\r
430      * </pre></blockquote>\r
431      *\r
432      * @param event Description of the key event.\r
433      * @return {@code true} if the event was handled.\r
434      */\r
435     public boolean dispatchKeyEvent(KeyEvent event) {\r
436         return false;\r
437     }\r
438 \r
439     /**\r
440      * Notify the action bar that the Activity has triggered a menu creation\r
441      * which should happen on the conclusion of {@link Activity#onCreate}. This\r
442      * will be used to gain a reference to the native menu for native and\r
443      * overflow binding as well as to indicate when compatibility create should\r
444      * occur for the first time.\r
445      *\r
446      * @param menu Activity native menu.\r
447      * @return {@code true} since we always want to say that we have a native\r
448      */\r
449     public abstract boolean dispatchCreateOptionsMenu(android.view.Menu menu);\r
450 \r
451     /**\r
452      * Notify the action bar that the Activity has triggered a menu preparation\r
453      * which usually means that the user has requested the overflow menu via a\r
454      * hardware menu key. You should return the result of this method call and\r
455      * not call the superclass implementation.\r
456      *\r
457      * <blockquote><p>\r
458      * @Override\r
459      * public final boolean onPrepareOptionsMenu(android.view.Menu menu) {\r
460      *     return mSherlock.dispatchPrepareOptionsMenu(menu);\r
461      * }\r
462      * </p></blockquote>\r
463      *\r
464      * @param menu Activity native menu.\r
465      * @return {@code true} if menu display should proceed.\r
466      */\r
467     public abstract boolean dispatchPrepareOptionsMenu(android.view.Menu menu);\r
468 \r
469     /**\r
470      * Notify the action bar that a native options menu item has been selected.\r
471      * The implementation should return the result of this method call.\r
472      *\r
473      * <blockquote><p>\r
474      * @Override\r
475      * public final boolean onOptionsItemSelected(android.view.MenuItem item) {\r
476      *     return mSherlock.dispatchOptionsItemSelected(item);\r
477      * }\r
478      * </p></blockquote>\r
479      *\r
480      * @param item Options menu item.\r
481      * @return @{code true} if the selection was handled.\r
482      */\r
483     public abstract boolean dispatchOptionsItemSelected(android.view.MenuItem item);\r
484 \r
485     /**\r
486      * Notify the action bar that the overflow menu has been opened. The\r
487      * implementation should conditionally return {@code true} if this method\r
488      * returns {@code true}, otherwise return the result of the superclass\r
489      * method.\r
490      *\r
491      * <blockquote><p>\r
492      * @Override\r
493      * public final boolean onMenuOpened(int featureId, android.view.Menu menu) {\r
494      *     if (mSherlock.dispatchMenuOpened(featureId, menu)) {\r
495      *         return true;\r
496      *     }\r
497      *     return super.onMenuOpened(featureId, menu);\r
498      * }\r
499      * </p></blockquote>\r
500      *\r
501      * @param featureId Window feature which triggered the event.\r
502      * @param menu Activity native menu.\r
503      * @return {@code true} if the event was handled by this method.\r
504      */\r
505     public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) {\r
506         return false;\r
507     }\r
508 \r
509     /**\r
510      * Notify the action bar that the overflow menu has been closed. This\r
511      * method should be called before the superclass implementation.\r
512      *\r
513      * <blockquote><p>\r
514      * @Override\r
515      * public void onPanelClosed(int featureId, android.view.Menu menu) {\r
516      *     mSherlock.dispatchPanelClosed(featureId, menu);\r
517      *     super.onPanelClosed(featureId, menu);\r
518      * }\r
519      * </p></blockquote>\r
520      *\r
521      * @param featureId\r
522      * @param menu\r
523      */\r
524     public void dispatchPanelClosed(int featureId, android.view.Menu menu) {}\r
525 \r
526     /**\r
527      * Notify the action bar that the activity has been destroyed. This method\r
528      * should be called before the superclass implementation.\r
529      *\r
530      * <blockquote><p>\r
531      * @Override\r
532      * public void onDestroy() {\r
533      *     mSherlock.dispatchDestroy();\r
534      *     super.onDestroy();\r
535      * }\r
536      * </p></blockquote>\r
537      */\r
538     public void dispatchDestroy() {}\r
539 \r
540 \r
541     ///////////////////////////////////////////////////////////////////////////\r
542     ///////////////////////////////////////////////////////////////////////////\r
543 \r
544 \r
545     /**\r
546      * Internal method to trigger the menu creation process.\r
547      *\r
548      * @return {@code true} if menu creation should proceed.\r
549      */\r
550     protected final boolean callbackCreateOptionsMenu(Menu menu) {\r
551         if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] menu: " + menu);\r
552 \r
553         boolean result = true;\r
554         if (mActivity instanceof OnCreatePanelMenuListener) {\r
555             OnCreatePanelMenuListener listener = (OnCreatePanelMenuListener)mActivity;\r
556             result = listener.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu);\r
557         } else if (mActivity instanceof OnCreateOptionsMenuListener) {\r
558             OnCreateOptionsMenuListener listener = (OnCreateOptionsMenuListener)mActivity;\r
559             result = listener.onCreateOptionsMenu(menu);\r
560         }\r
561 \r
562         if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] returning " + result);\r
563         return result;\r
564     }\r
565 \r
566     /**\r
567      * Internal method to trigger the menu preparation process.\r
568      *\r
569      * @return {@code true} if menu preparation should proceed.\r
570      */\r
571     protected final boolean callbackPrepareOptionsMenu(Menu menu) {\r
572         if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] menu: " + menu);\r
573 \r
574         boolean result = true;\r
575         if (mActivity instanceof OnPreparePanelListener) {\r
576             OnPreparePanelListener listener = (OnPreparePanelListener)mActivity;\r
577             result = listener.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu);\r
578         } else if (mActivity instanceof OnPrepareOptionsMenuListener) {\r
579             OnPrepareOptionsMenuListener listener = (OnPrepareOptionsMenuListener)mActivity;\r
580             result = listener.onPrepareOptionsMenu(menu);\r
581         }\r
582 \r
583         if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] returning " + result);\r
584         return result;\r
585     }\r
586 \r
587     /**\r
588      * Internal method for dispatching options menu selection to the owning\r
589      * activity callback.\r
590      *\r
591      * @param item Selected options menu item.\r
592      * @return {@code true} if the item selection was handled in the callback.\r
593      */\r
594     protected final boolean callbackOptionsItemSelected(MenuItem item) {\r
595         if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] item: " + item.getTitleCondensed());\r
596 \r
597         boolean result = false;\r
598         if (mActivity instanceof OnMenuItemSelectedListener) {\r
599             OnMenuItemSelectedListener listener = (OnMenuItemSelectedListener)mActivity;\r
600             result = listener.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item);\r
601         } else if (mActivity instanceof OnOptionsItemSelectedListener) {\r
602             OnOptionsItemSelectedListener listener = (OnOptionsItemSelectedListener)mActivity;\r
603             result = listener.onOptionsItemSelected(item);\r
604         }\r
605 \r
606         if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] returning " + result);\r
607         return result;\r
608     }\r
609 \r
610 \r
611     ///////////////////////////////////////////////////////////////////////////\r
612     ///////////////////////////////////////////////////////////////////////////\r
613 \r
614 \r
615     /**\r
616      * Query for the availability of a certain feature.\r
617      *\r
618      * @param featureId The feature ID to check.\r
619      * @return {@code true} if feature is enabled, {@code false} otherwise.\r
620      */\r
621     public abstract boolean hasFeature(int featureId);\r
622 \r
623     /**\r
624      * Enable extended screen features. This must be called before\r
625      * {@code setContentView()}. May be called as many times as desired as long\r
626      * as it is before {@code setContentView()}. If not called, no extended\r
627      * features will be available. You can not turn off a feature once it is\r
628      * requested.\r
629      *\r
630      * @param featureId The desired features, defined as constants by Window.\r
631      * @return Returns true if the requested feature is supported and now\r
632      * enabled.\r
633      */\r
634     public abstract boolean requestFeature(int featureId);\r
635 \r
636     /**\r
637      * Set extra options that will influence the UI for this window.\r
638      *\r
639      * @param uiOptions Flags specifying extra options for this window.\r
640      */\r
641     public abstract void setUiOptions(int uiOptions);\r
642 \r
643     /**\r
644      * Set extra options that will influence the UI for this window. Only the\r
645      * bits filtered by mask will be modified.\r
646      *\r
647      * @param uiOptions Flags specifying extra options for this window.\r
648      * @param mask Flags specifying which options should be modified. Others\r
649      *             will remain unchanged.\r
650      */\r
651     public abstract void setUiOptions(int uiOptions, int mask);\r
652 \r
653     /**\r
654      * Set the content of the activity inside the action bar.\r
655      *\r
656      * @param layoutResId Layout resource ID.\r
657      */\r
658     public abstract void setContentView(int layoutResId);\r
659 \r
660     /**\r
661      * Set the content of the activity inside the action bar.\r
662      *\r
663      * @param view The desired content to display.\r
664      */\r
665     public void setContentView(View view) {\r
666         if (DEBUG) Log.d(TAG, "[setContentView] view: " + view);\r
667 \r
668         setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));\r
669     }\r
670 \r
671     /**\r
672      * Set the content of the activity inside the action bar.\r
673      *\r
674      * @param view The desired content to display.\r
675      * @param params Layout parameters to apply to the view.\r
676      */\r
677     public abstract void setContentView(View view, ViewGroup.LayoutParams params);\r
678 \r
679     /**\r
680      * Variation on {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}\r
681      * to add an additional content view to the screen. Added after any\r
682      * existing ones on the screen -- existing views are NOT removed.\r
683      *\r
684      * @param view The desired content to display.\r
685      * @param params Layout parameters for the view.\r
686      */\r
687     public abstract void addContentView(View view, ViewGroup.LayoutParams params);\r
688 \r
689     /**\r
690      * Change the title associated with this activity.\r
691      */\r
692     public abstract void setTitle(CharSequence title);\r
693 \r
694     /**\r
695      * Change the title associated with this activity.\r
696      */\r
697     public void setTitle(int resId) {\r
698         if (DEBUG) Log.d(TAG, "[setTitle] resId: " + resId);\r
699 \r
700         setTitle(mActivity.getString(resId));\r
701     }\r
702 \r
703     /**\r
704      * Sets the visibility of the progress bar in the title.\r
705      * <p>\r
706      * In order for the progress bar to be shown, the feature must be requested\r
707      * via {@link #requestWindowFeature(int)}.\r
708      *\r
709      * @param visible Whether to show the progress bars in the title.\r
710      */\r
711     public abstract void setProgressBarVisibility(boolean visible);\r
712 \r
713     /**\r
714      * Sets the visibility of the indeterminate progress bar in the title.\r
715      * <p>\r
716      * In order for the progress bar to be shown, the feature must be requested\r
717      * via {@link #requestWindowFeature(int)}.\r
718      *\r
719      * @param visible Whether to show the progress bars in the title.\r
720      */\r
721     public abstract void setProgressBarIndeterminateVisibility(boolean visible);\r
722 \r
723     /**\r
724      * Sets whether the horizontal progress bar in the title should be indeterminate (the circular\r
725      * is always indeterminate).\r
726      * <p>\r
727      * In order for the progress bar to be shown, the feature must be requested\r
728      * via {@link #requestWindowFeature(int)}.\r
729      *\r
730      * @param indeterminate Whether the horizontal progress bar should be indeterminate.\r
731      */\r
732     public abstract void setProgressBarIndeterminate(boolean indeterminate);\r
733 \r
734     /**\r
735      * Sets the progress for the progress bars in the title.\r
736      * <p>\r
737      * In order for the progress bar to be shown, the feature must be requested\r
738      * via {@link #requestWindowFeature(int)}.\r
739      *\r
740      * @param progress The progress for the progress bar. Valid ranges are from\r
741      *            0 to 10000 (both inclusive). If 10000 is given, the progress\r
742      *            bar will be completely filled and will fade out.\r
743      */\r
744     public abstract void setProgress(int progress);\r
745 \r
746     /**\r
747      * Sets the secondary progress for the progress bar in the title. This\r
748      * progress is drawn between the primary progress (set via\r
749      * {@link #setProgress(int)} and the background. It can be ideal for media\r
750      * scenarios such as showing the buffering progress while the default\r
751      * progress shows the play progress.\r
752      * <p>\r
753      * In order for the progress bar to be shown, the feature must be requested\r
754      * via {@link #requestWindowFeature(int)}.\r
755      *\r
756      * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from\r
757      *            0 to 10000 (both inclusive).\r
758      */\r
759     public abstract void setSecondaryProgress(int secondaryProgress);\r
760 \r
761     /**\r
762      * Get a menu inflater instance which supports the newer menu attributes.\r
763      *\r
764      * @return Menu inflater instance.\r
765      */\r
766     public MenuInflater getMenuInflater() {\r
767         if (DEBUG) Log.d(TAG, "[getMenuInflater]");\r
768 \r
769         // Make sure that action views can get an appropriate theme.\r
770         if (mMenuInflater == null) {\r
771             if (getActionBar() != null) {\r
772                 mMenuInflater = new MenuInflater(getThemedContext());\r
773             } else {\r
774                 mMenuInflater = new MenuInflater(mActivity);\r
775             }\r
776         }\r
777         return mMenuInflater;\r
778     }\r
779 \r
780     protected abstract Context getThemedContext();\r
781 \r
782     /**\r
783      * Start an action mode.\r
784      *\r
785      * @param callback Callback that will manage lifecycle events for this\r
786      *                 context mode.\r
787      * @return The ContextMode that was started, or null if it was canceled.\r
788      * @see ActionMode\r
789      */\r
790     public abstract ActionMode startActionMode(ActionMode.Callback callback);\r
791 }\r