1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v7.app;
18
19import android.content.Context;
20import android.content.pm.ActivityInfo;
21import android.content.res.Configuration;
22import android.os.Bundle;
23import android.support.v4.app.ActionBarDrawerToggle;
24import android.support.v4.view.WindowCompat;
25import android.support.v7.internal.view.ActionModeWrapper;
26import android.support.v7.internal.view.menu.MenuWrapperFactory;
27import android.support.v7.view.ActionMode;
28import android.view.KeyEvent;
29import android.view.Menu;
30import android.view.MenuItem;
31import android.view.MotionEvent;
32import android.view.View;
33import android.view.ViewGroup;
34import android.view.Window;
35import android.view.WindowManager;
36import android.view.accessibility.AccessibilityEvent;
37
38class ActionBarActivityDelegateICS extends ActionBarActivityDelegate {
39    Menu mMenu;
40
41    ActionBarActivityDelegateICS(ActionBarActivity activity) {
42        super(activity);
43    }
44
45    @Override
46    public ActionBar createSupportActionBar() {
47        return new ActionBarImplICS(mActivity, mActivity);
48    }
49
50    @Override
51    public void onCreate(Bundle savedInstanceState) {
52        // Set framework uiOptions from the support metadata value
53        if (UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW.equals(getUiOptionsFromMetadata())) {
54            mActivity.getWindow().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW,
55                    ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
56        }
57
58        super.onCreate(savedInstanceState);
59
60        if (mHasActionBar) {
61            // If action bar is requested by inheriting from the appcompat theme,
62            // the system will not know about that. So explicitly request for an action bar.
63            mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
64        }
65        if (mOverlayActionBar) {
66            mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY);
67        }
68
69        /*
70         * This goofy move needs some explanation.
71         *
72         * The verifier on older platform versions has some interesting side effects if
73         * a class defines a method that takes a parameter of a type that doesn't exist.
74         * In this case, that type is android.view.ActionMode. Therefore, ActionBarActivity
75         * cannot override the onActionModeStarted/Finished methods without causing nastiness
76         * when it is loaded on older platform versions.
77         *
78         * Since these methods are actually part of the window callback and not intrinsic to
79         * Activity itself, we can install a little shim with the window instead that knows
80         * about the ActionMode class. Note that this means that any new methods added to
81         * Window.Callback in the future won't get proxied without updating the support lib,
82         * but we shouldn't be adding new methods to public interfaces that way anyway...right? ;)
83         */
84        final Window w = mActivity.getWindow();
85        w.setCallback(createWindowCallbackWrapper(w.getCallback()));
86    }
87
88    Window.Callback createWindowCallbackWrapper(Window.Callback cb) {
89        return new WindowCallbackWrapper(cb);
90    }
91
92    @Override
93    public void onConfigurationChanged(Configuration newConfig) {
94    }
95
96    @Override
97    public void onStop() {
98    }
99
100    @Override
101    public void onPostResume() {
102    }
103
104    @Override
105    public void setContentView(View v) {
106        mActivity.superSetContentView(v);
107    }
108
109    @Override
110    public void setContentView(int resId) {
111        mActivity.superSetContentView(resId);
112    }
113
114    @Override
115    public void setContentView(View v, ViewGroup.LayoutParams lp) {
116        mActivity.superSetContentView(v, lp);
117    }
118
119    @Override
120    public void addContentView(View v, ViewGroup.LayoutParams lp) {
121        mActivity.superAddContentView(v, lp);
122    }
123
124    @Override
125    public void onContentChanged() {
126        // Call straight through to the support version of the method
127        mActivity.onSupportContentChanged();
128    }
129
130    @Override
131    public boolean supportRequestWindowFeature(int featureId) {
132        return mActivity.requestWindowFeature(featureId);
133    }
134
135    @Override
136    public View onCreatePanelView(int featureId) {
137        // Do not create custom options menu on HC+
138        return null;
139    }
140
141    @Override
142    public boolean onCreatePanelMenu(int featureId, Menu menu) {
143        if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) {
144            if (mMenu == null) {
145                mMenu = MenuWrapperFactory.createMenuWrapper(menu);
146            }
147            return mActivity.superOnCreatePanelMenu(featureId, mMenu);
148        }
149        return mActivity.superOnCreatePanelMenu(featureId, menu);
150    }
151
152    @Override
153    public boolean onPreparePanel(int featureId, View view, Menu menu) {
154        if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) {
155            return mActivity.superOnPreparePanel(featureId, view, mMenu);
156        }
157        return mActivity.superOnPreparePanel(featureId, view, menu);
158    }
159
160    @Override
161    public boolean onMenuItemSelected(int featureId, MenuItem item) {
162        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
163            item = MenuWrapperFactory.createMenuItemWrapper(item);
164        }
165        return mActivity.superOnMenuItemSelected(featureId, item);
166    }
167
168    @Override
169    public void onTitleChanged(CharSequence title) {
170        // Handled by framework
171    }
172
173    @Override
174    public ActionMode startSupportActionMode(ActionMode.Callback callback) {
175        if (callback == null) {
176            throw new IllegalArgumentException("ActionMode callback can not be null.");
177        }
178
179        Context context = getActionBarThemedContext();
180
181        ActionModeWrapper.CallbackWrapper wrappedCallback = new ActionModeWrapper.CallbackWrapper(
182                context, callback);
183        ActionModeWrapper wrappedMode = null;
184
185        android.view.ActionMode frameworkMode = mActivity.startActionMode(wrappedCallback);
186
187        if (frameworkMode != null) {
188            wrappedMode = new ActionModeWrapper(context, frameworkMode);
189            wrappedCallback.setLastStartedActionMode(wrappedMode);
190        }
191
192        return wrappedMode;
193    }
194
195    public void onActionModeStarted(android.view.ActionMode mode) {
196        mActivity.onSupportActionModeStarted(
197                new ActionModeWrapper(getActionBarThemedContext(), mode));
198    }
199
200    @Override
201    void setSupportProgressBarVisibility(boolean visible) {
202        mActivity.setProgressBarVisibility(visible);
203    }
204
205    @Override
206    void setSupportProgressBarIndeterminateVisibility(boolean visible) {
207        mActivity.setProgressBarIndeterminateVisibility(visible);
208    }
209
210    @Override
211    void setSupportProgressBarIndeterminate(boolean indeterminate) {
212        mActivity.setProgressBarIndeterminate(indeterminate);
213    }
214
215    @Override
216    void setSupportProgress(int progress) {
217        mActivity.setProgress(progress);
218    }
219
220    public void onActionModeFinished(android.view.ActionMode mode) {
221        mActivity.onSupportActionModeFinished(
222                new ActionModeWrapper(getActionBarThemedContext(), mode));
223    }
224
225    @Override
226    public void supportInvalidateOptionsMenu() {
227        mMenu = null;
228    }
229
230    @Override
231    public boolean onBackPressed() {
232        return false;
233    }
234
235    @Override
236    public ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
237        // Return null so that ActionBarDrawableToggle uses it's standard impl
238        return null;
239    }
240
241    class WindowCallbackWrapper implements Window.Callback {
242        final Window.Callback mWrapped;
243
244        public WindowCallbackWrapper(Window.Callback wrapped) {
245            mWrapped = wrapped;
246        }
247
248        @Override
249        public boolean dispatchKeyEvent(KeyEvent event) {
250            return mWrapped.dispatchKeyEvent(event);
251        }
252
253        @Override
254        public boolean dispatchKeyShortcutEvent(KeyEvent event) {
255            return mWrapped.dispatchKeyShortcutEvent(event);
256        }
257
258        @Override
259        public boolean dispatchTouchEvent(MotionEvent event) {
260            return mWrapped.dispatchTouchEvent(event);
261        }
262
263        @Override
264        public boolean dispatchTrackballEvent(MotionEvent event) {
265            return mWrapped.dispatchTrackballEvent(event);
266        }
267
268        @Override
269        public boolean dispatchGenericMotionEvent(MotionEvent event) {
270            return mWrapped.dispatchGenericMotionEvent(event);
271        }
272
273        @Override
274        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
275            return mWrapped.dispatchPopulateAccessibilityEvent(event);
276        }
277
278        @Override
279        public View onCreatePanelView(int featureId) {
280            return mWrapped.onCreatePanelView(featureId);
281        }
282
283        @Override
284        public boolean onCreatePanelMenu(int featureId, Menu menu) {
285            return mWrapped.onCreatePanelMenu(featureId, menu);
286        }
287
288        @Override
289        public boolean onPreparePanel(int featureId, View view, Menu menu) {
290            return mWrapped.onPreparePanel(featureId, view, menu);
291        }
292
293        @Override
294        public boolean onMenuOpened(int featureId, Menu menu) {
295            return mWrapped.onMenuOpened(featureId, menu);
296        }
297
298        @Override
299        public boolean onMenuItemSelected(int featureId, MenuItem item) {
300            return mWrapped.onMenuItemSelected(featureId, item);
301        }
302
303        @Override
304        public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {
305            mWrapped.onWindowAttributesChanged(attrs);
306        }
307
308        @Override
309        public void onContentChanged() {
310            mWrapped.onContentChanged();
311        }
312
313        @Override
314        public void onWindowFocusChanged(boolean hasFocus) {
315            mWrapped.onWindowFocusChanged(hasFocus);
316        }
317
318        @Override
319        public void onAttachedToWindow() {
320            mWrapped.onAttachedToWindow();
321        }
322
323        @Override
324        public void onDetachedFromWindow() {
325            mWrapped.onDetachedFromWindow();
326        }
327
328        @Override
329        public void onPanelClosed(int featureId, Menu menu) {
330            mWrapped.onPanelClosed(featureId, menu);
331        }
332
333        @Override
334        public boolean onSearchRequested() {
335            return mWrapped.onSearchRequested();
336        }
337
338        @Override
339        public android.view.ActionMode onWindowStartingActionMode(
340                android.view.ActionMode.Callback callback) {
341            return mWrapped.onWindowStartingActionMode(callback);
342        }
343
344        /*
345         * And here are the money methods, the reason why this wrapper exists:
346         */
347
348        @Override
349        public void onActionModeStarted(android.view.ActionMode mode) {
350            mWrapped.onActionModeStarted(mode);
351            ActionBarActivityDelegateICS.this.onActionModeStarted(mode);
352        }
353
354        @Override
355        public void onActionModeFinished(android.view.ActionMode mode) {
356            mWrapped.onActionModeFinished(mode);
357            ActionBarActivityDelegateICS.this.onActionModeFinished(mode);
358        }
359    }
360}
361