a7cc25d3e0736c311ccb2bfa522791379234cda5
[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     ///////////////////////////////////////////////////////////////////////////\r
528     ///////////////////////////////////////////////////////////////////////////\r
529 \r
530 \r
531     /**\r
532      * Internal method to trigger the menu creation process.\r
533      *\r
534      * @return {@code true} if menu creation should proceed.\r
535      */\r
536     protected final boolean callbackCreateOptionsMenu(Menu menu) {\r
537         if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] menu: " + menu);\r
538 \r
539         boolean result = true;\r
540         if (mActivity instanceof OnCreatePanelMenuListener) {\r
541             OnCreatePanelMenuListener listener = (OnCreatePanelMenuListener)mActivity;\r
542             result = listener.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu);\r
543         } else if (mActivity instanceof OnCreateOptionsMenuListener) {\r
544             OnCreateOptionsMenuListener listener = (OnCreateOptionsMenuListener)mActivity;\r
545             result = listener.onCreateOptionsMenu(menu);\r
546         }\r
547 \r
548         if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] returning " + result);\r
549         return result;\r
550     }\r
551 \r
552     /**\r
553      * Internal method to trigger the menu preparation process.\r
554      *\r
555      * @return {@code true} if menu preparation should proceed.\r
556      */\r
557     protected final boolean callbackPrepareOptionsMenu(Menu menu) {\r
558         if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] menu: " + menu);\r
559 \r
560         boolean result = true;\r
561         if (mActivity instanceof OnPreparePanelListener) {\r
562             OnPreparePanelListener listener = (OnPreparePanelListener)mActivity;\r
563             result = listener.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu);\r
564         } else if (mActivity instanceof OnPrepareOptionsMenuListener) {\r
565             OnPrepareOptionsMenuListener listener = (OnPrepareOptionsMenuListener)mActivity;\r
566             result = listener.onPrepareOptionsMenu(menu);\r
567         }\r
568 \r
569         if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] returning " + result);\r
570         return result;\r
571     }\r
572 \r
573     /**\r
574      * Internal method for dispatching options menu selection to the owning\r
575      * activity callback.\r
576      *\r
577      * @param item Selected options menu item.\r
578      * @return {@code true} if the item selection was handled in the callback.\r
579      */\r
580     protected final boolean callbackOptionsItemSelected(MenuItem item) {\r
581         if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] item: " + item.getTitleCondensed());\r
582 \r
583         boolean result = false;\r
584         if (mActivity instanceof OnMenuItemSelectedListener) {\r
585             OnMenuItemSelectedListener listener = (OnMenuItemSelectedListener)mActivity;\r
586             result = listener.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item);\r
587         } else if (mActivity instanceof OnOptionsItemSelectedListener) {\r
588             OnOptionsItemSelectedListener listener = (OnOptionsItemSelectedListener)mActivity;\r
589             result = listener.onOptionsItemSelected(item);\r
590         }\r
591 \r
592         if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] returning " + result);\r
593         return result;\r
594     }\r
595 \r
596 \r
597     ///////////////////////////////////////////////////////////////////////////\r
598     ///////////////////////////////////////////////////////////////////////////\r
599 \r
600 \r
601     /**\r
602      * Query for the availability of a certain feature.\r
603      *\r
604      * @param featureId The feature ID to check.\r
605      * @return {@code true} if feature is enabled, {@code false} otherwise.\r
606      */\r
607     public abstract boolean hasFeature(int featureId);\r
608 \r
609     /**\r
610      * Enable extended screen features. This must be called before\r
611      * {@code setContentView()}. May be called as many times as desired as long\r
612      * as it is before {@code setContentView()}. If not called, no extended\r
613      * features will be available. You can not turn off a feature once it is\r
614      * requested.\r
615      *\r
616      * @param featureId The desired features, defined as constants by Window.\r
617      * @return Returns true if the requested feature is supported and now\r
618      * enabled.\r
619      */\r
620     public abstract boolean requestFeature(int featureId);\r
621 \r
622     /**\r
623      * Set extra options that will influence the UI for this window.\r
624      *\r
625      * @param uiOptions Flags specifying extra options for this window.\r
626      */\r
627     public abstract void setUiOptions(int uiOptions);\r
628 \r
629     /**\r
630      * Set extra options that will influence the UI for this window. Only the\r
631      * bits filtered by mask will be modified.\r
632      *\r
633      * @param uiOptions Flags specifying extra options for this window.\r
634      * @param mask Flags specifying which options should be modified. Others\r
635      *             will remain unchanged.\r
636      */\r
637     public abstract void setUiOptions(int uiOptions, int mask);\r
638 \r
639     /**\r
640      * Set the content of the activity inside the action bar.\r
641      *\r
642      * @param layoutResId Layout resource ID.\r
643      */\r
644     public abstract void setContentView(int layoutResId);\r
645 \r
646     /**\r
647      * Set the content of the activity inside the action bar.\r
648      *\r
649      * @param view The desired content to display.\r
650      */\r
651     public void setContentView(View view) {\r
652         if (DEBUG) Log.d(TAG, "[setContentView] view: " + view);\r
653 \r
654         setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));\r
655     }\r
656 \r
657     /**\r
658      * Set the content of the activity inside the action bar.\r
659      *\r
660      * @param view The desired content to display.\r
661      * @param params Layout parameters to apply to the view.\r
662      */\r
663     public abstract void setContentView(View view, ViewGroup.LayoutParams params);\r
664 \r
665     /**\r
666      * Variation on {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}\r
667      * to add an additional content view to the screen. Added after any\r
668      * existing ones on the screen -- existing views are NOT removed.\r
669      *\r
670      * @param view The desired content to display.\r
671      * @param params Layout parameters for the view.\r
672      */\r
673     public abstract void addContentView(View view, ViewGroup.LayoutParams params);\r
674 \r
675     /**\r
676      * Change the title associated with this activity.\r
677      */\r
678     public abstract void setTitle(CharSequence title);\r
679 \r
680     /**\r
681      * Change the title associated with this activity.\r
682      */\r
683     public void setTitle(int resId) {\r
684         if (DEBUG) Log.d(TAG, "[setTitle] resId: " + resId);\r
685 \r
686         setTitle(mActivity.getString(resId));\r
687     }\r
688 \r
689     /**\r
690      * Sets the visibility of the progress bar in the title.\r
691      * <p>\r
692      * In order for the progress bar to be shown, the feature must be requested\r
693      * via {@link #requestWindowFeature(int)}.\r
694      *\r
695      * @param visible Whether to show the progress bars in the title.\r
696      */\r
697     public abstract void setProgressBarVisibility(boolean visible);\r
698 \r
699     /**\r
700      * Sets the visibility of the indeterminate progress bar in the title.\r
701      * <p>\r
702      * In order for the progress bar to be shown, the feature must be requested\r
703      * via {@link #requestWindowFeature(int)}.\r
704      *\r
705      * @param visible Whether to show the progress bars in the title.\r
706      */\r
707     public abstract void setProgressBarIndeterminateVisibility(boolean visible);\r
708 \r
709     /**\r
710      * Sets whether the horizontal progress bar in the title should be indeterminate (the circular\r
711      * is always indeterminate).\r
712      * <p>\r
713      * In order for the progress bar to be shown, the feature must be requested\r
714      * via {@link #requestWindowFeature(int)}.\r
715      *\r
716      * @param indeterminate Whether the horizontal progress bar should be indeterminate.\r
717      */\r
718     public abstract void setProgressBarIndeterminate(boolean indeterminate);\r
719 \r
720     /**\r
721      * Sets the progress for the progress bars in the title.\r
722      * <p>\r
723      * In order for the progress bar to be shown, the feature must be requested\r
724      * via {@link #requestWindowFeature(int)}.\r
725      *\r
726      * @param progress The progress for the progress bar. Valid ranges are from\r
727      *            0 to 10000 (both inclusive). If 10000 is given, the progress\r
728      *            bar will be completely filled and will fade out.\r
729      */\r
730     public abstract void setProgress(int progress);\r
731 \r
732     /**\r
733      * Sets the secondary progress for the progress bar in the title. This\r
734      * progress is drawn between the primary progress (set via\r
735      * {@link #setProgress(int)} and the background. It can be ideal for media\r
736      * scenarios such as showing the buffering progress while the default\r
737      * progress shows the play progress.\r
738      * <p>\r
739      * In order for the progress bar to be shown, the feature must be requested\r
740      * via {@link #requestWindowFeature(int)}.\r
741      *\r
742      * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from\r
743      *            0 to 10000 (both inclusive).\r
744      */\r
745     public abstract void setSecondaryProgress(int secondaryProgress);\r
746 \r
747     /**\r
748      * Get a menu inflater instance which supports the newer menu attributes.\r
749      *\r
750      * @return Menu inflater instance.\r
751      */\r
752     public MenuInflater getMenuInflater() {\r
753         if (DEBUG) Log.d(TAG, "[getMenuInflater]");\r
754 \r
755         // Make sure that action views can get an appropriate theme.\r
756         if (mMenuInflater == null) {\r
757             if (getActionBar() != null) {\r
758                 mMenuInflater = new MenuInflater(getThemedContext());\r
759             } else {\r
760                 mMenuInflater = new MenuInflater(mActivity);\r
761             }\r
762         }\r
763         return mMenuInflater;\r
764     }\r
765 \r
766     protected abstract Context getThemedContext();\r
767 \r
768     /**\r
769      * Start an action mode.\r
770      *\r
771      * @param callback Callback that will manage lifecycle events for this\r
772      *                 context mode.\r
773      * @return The ContextMode that was started, or null if it was canceled.\r
774      * @see ActionMode\r
775      */\r
776     public abstract ActionMode startActionMode(ActionMode.Callback callback);\r
777 }\r