blob: 8fa4d4372cb9fa7a98fd1a8bd1880e3f2fbc1f58 [file] [log] [blame]
John Reck0f602f32011-07-07 15:38:43 -07001/*
2 * Copyright (C) 2010 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 com.android.browser;
18
19import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.ObjectAnimator;
22import android.content.Context;
23import android.content.res.Resources;
24import android.view.Gravity;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
Ben Murdochd51bb572011-08-17 20:42:02 +010028import android.view.ViewStub;
John Reck0f602f32011-07-07 15:38:43 -070029import android.view.animation.Animation;
30import android.view.animation.Animation.AnimationListener;
31import android.view.animation.AnimationUtils;
32import android.view.animation.DecelerateInterpolator;
33import android.webkit.WebView;
34import android.widget.AbsoluteLayout;
35import android.widget.FrameLayout;
36import android.widget.RelativeLayout;
37
38
39/**
40 * Base class for a title bar used by the browser.
41 */
42public class TitleBar extends RelativeLayout {
43
44 private static final int PROGRESS_MAX = 100;
45 private static final float ANIM_TITLEBAR_DECELERATE = 2.5f;
46
47 private UiController mUiController;
48 private BaseUi mBaseUi;
49 private FrameLayout mParent;
50 private PageProgressView mProgress;
51
52 private AutologinBar mAutoLogin;
53 private NavigationBarBase mNavBar;
54 private boolean mUseQuickControls;
John Reckef654f12011-07-12 16:42:08 -070055 private SnapshotBar mSnapshotBar;
John Reck0f602f32011-07-07 15:38:43 -070056
57 //state
58 private boolean mShowing;
59 private boolean mInLoad;
60 private boolean mSkipTitleBarAnimations;
61 private Animator mTitleBarAnimator;
62
63 public TitleBar(Context context, UiController controller, BaseUi ui,
64 FrameLayout parent) {
65 super(context, null);
66 mUiController = controller;
67 mBaseUi = ui;
68 mParent = parent;
69 initLayout(context);
70 }
71
72 private void initLayout(Context context) {
73 LayoutInflater factory = LayoutInflater.from(context);
74 factory.inflate(R.layout.title_bar, this);
75 mProgress = (PageProgressView) findViewById(R.id.progress);
John Reck0f602f32011-07-07 15:38:43 -070076 mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
77 mNavBar.setTitleBar(this);
Ben Murdochd51bb572011-08-17 20:42:02 +010078 }
79
80 private void inflateAutoLoginBar() {
81 if (mAutoLogin != null) {
82 return;
83 }
84
85 ViewStub stub = (ViewStub) findViewById(R.id.autologin_stub);
86 mAutoLogin = (AutologinBar) stub.inflate();
87 mAutoLogin.setTitleBar(this);
88 }
89
90 private void inflateSnapshotBar() {
91 if (mSnapshotBar != null) {
92 return;
93 }
94
95 ViewStub stub = (ViewStub) findViewById(R.id.snapshotbar_stub);
96 mSnapshotBar = (SnapshotBar) stub.inflate();
John Reckef654f12011-07-12 16:42:08 -070097 mSnapshotBar.setTitleBar(this);
John Reck0f602f32011-07-07 15:38:43 -070098 }
99
100 public BaseUi getUi() {
101 return mBaseUi;
102 }
103
104 public UiController getUiController() {
105 return mUiController;
106 }
107
108 public void setUseQuickControls(boolean use) {
109 mUseQuickControls = use;
110 setLayoutParams(makeLayoutParams());
111 }
112
113 void setShowProgressOnly(boolean progress) {
John Reckef654f12011-07-12 16:42:08 -0700114 if (progress && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700115 mNavBar.setVisibility(View.GONE);
116 } else {
117 mNavBar.setVisibility(View.VISIBLE);
118 }
119 }
120
121 void setSkipTitleBarAnimations(boolean skip) {
122 mSkipTitleBarAnimations = skip;
123 }
124
125 void setupTitleBarAnimator(Animator animator) {
126 Resources res = mContext.getResources();
127 int duration = res.getInteger(R.integer.titlebar_animation_duration);
128 animator.setInterpolator(new DecelerateInterpolator(
129 ANIM_TITLEBAR_DECELERATE));
130 animator.setDuration(duration);
131 }
132
133 void show() {
134 if (mUseQuickControls) {
135 mParent.addView(this);
136 } else {
137 if (!mSkipTitleBarAnimations) {
138 cancelTitleBarAnimation(false);
139 int visibleHeight = getVisibleTitleHeight();
140 float startPos = (-getEmbeddedHeight() + visibleHeight);
141 if (getTranslationY() != 0) {
142 startPos = Math.max(startPos, getTranslationY());
143 }
144 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
145 "translationY",
146 startPos, 0);
147 setupTitleBarAnimator(mTitleBarAnimator);
148 mTitleBarAnimator.start();
149 }
150 mBaseUi.setTitleGravity(Gravity.TOP);
151 }
152 mShowing = true;
153 }
154
155 void hide() {
156 if (mUseQuickControls) {
157 mParent.removeView(this);
158 } else {
159 if (!mSkipTitleBarAnimations) {
160 cancelTitleBarAnimation(false);
161 int visibleHeight = getVisibleTitleHeight();
162 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
163 "translationY", getTranslationY(),
164 (-getEmbeddedHeight() + visibleHeight));
165 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
166 setupTitleBarAnimator(mTitleBarAnimator);
167 mTitleBarAnimator.start();
168 } else {
169 mBaseUi.setTitleGravity(Gravity.NO_GRAVITY);
170 }
171 }
172 mShowing = false;
173 }
174
175 boolean isShowing() {
176 return mShowing;
177 }
178
179 void cancelTitleBarAnimation(boolean reset) {
180 if (mTitleBarAnimator != null) {
181 mTitleBarAnimator.cancel();
182 mTitleBarAnimator = null;
183 }
184 if (reset) {
185 setTranslationY(0);
186 }
187 }
188
189 private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
190
191 boolean mWasCanceled;
192 @Override
193 public void onAnimationStart(Animator animation) {
194 mWasCanceled = false;
195 }
196
197 @Override
198 public void onAnimationRepeat(Animator animation) {
199 }
200
201 @Override
202 public void onAnimationEnd(Animator animation) {
203 if (!mWasCanceled) {
204 setTranslationY(0);
205 }
206 mBaseUi.setTitleGravity(Gravity.NO_GRAVITY);
207 }
208
209 @Override
210 public void onAnimationCancel(Animator animation) {
211 mWasCanceled = true;
212 }
213 };
214
215 private int getVisibleTitleHeight() {
216 Tab tab = mBaseUi.getActiveTab();
217 WebView webview = tab != null ? tab.getWebView() : null;
218 return webview != null ? webview.getVisibleTitleHeight() : 0;
219 }
220
221 /**
222 * Update the progress, from 0 to 100.
223 */
224 public void setProgress(int newProgress) {
225 if (newProgress >= PROGRESS_MAX) {
226 mProgress.setProgress(PageProgressView.MAX_PROGRESS);
227 mProgress.setVisibility(View.GONE);
228 mInLoad = false;
229 mNavBar.onProgressStopped();
230 // check if needs to be hidden
John Reckef654f12011-07-12 16:42:08 -0700231 if (!isEditingUrl() && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700232 hide();
233 if (mUseQuickControls) {
234 setShowProgressOnly(false);
235 }
236 }
237 } else {
238 if (!mInLoad) {
239 mProgress.setVisibility(View.VISIBLE);
240 mInLoad = true;
241 mNavBar.onProgressStarted();
242 }
243 mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
244 / PROGRESS_MAX);
245 if (!mShowing) {
246 if (mUseQuickControls && !isEditingUrl()) {
247 setShowProgressOnly(true);
248 }
249 show();
250 }
251 }
252 }
253
254 public int getEmbeddedHeight() {
255 int height = mNavBar.getHeight();
Ben Murdochd51bb572011-08-17 20:42:02 +0100256 if (mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE) {
John Reck0f602f32011-07-07 15:38:43 -0700257 height += mAutoLogin.getHeight();
258 }
259 return height;
260 }
261
262 public void updateAutoLogin(Tab tab, boolean animate) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100263 if (mAutoLogin == null) {
264 if (tab.getDeviceAccountLogin() == null) {
265 return;
266 }
267 inflateAutoLoginBar();
268 }
John Reck0f602f32011-07-07 15:38:43 -0700269 mAutoLogin.updateAutoLogin(tab, animate);
270 }
271
272 public void showAutoLogin(boolean animate) {
273 if (mUseQuickControls) {
274 mBaseUi.showTitleBar();
275 }
Ben Murdochd51bb572011-08-17 20:42:02 +0100276 if (mAutoLogin == null) {
277 inflateAutoLoginBar();
278 }
John Reck0f602f32011-07-07 15:38:43 -0700279 mAutoLogin.setVisibility(View.VISIBLE);
280 if (animate) {
281 mAutoLogin.startAnimation(AnimationUtils.loadAnimation(
282 getContext(), R.anim.autologin_enter));
283 }
284 }
285
286 public void hideAutoLogin(boolean animate) {
287 if (mUseQuickControls) {
288 mBaseUi.hideTitleBar();
289 mAutoLogin.setVisibility(View.GONE);
290 mBaseUi.refreshWebView();
291 } else {
292 if (animate) {
293 Animation anim = AnimationUtils.loadAnimation(getContext(),
294 R.anim.autologin_exit);
295 anim.setAnimationListener(new AnimationListener() {
296 @Override
297 public void onAnimationEnd(Animation a) {
298 mAutoLogin.setVisibility(View.GONE);
299 mBaseUi.refreshWebView();
300 }
301
302 @Override
303 public void onAnimationStart(Animation a) {
304 }
305
306 @Override
307 public void onAnimationRepeat(Animation a) {
308 }
309 });
310 mAutoLogin.startAnimation(anim);
311 } else if (mAutoLogin.getAnimation() == null) {
312 mAutoLogin.setVisibility(View.GONE);
313 mBaseUi.refreshWebView();
314 }
315 }
316 }
317
John Reckef654f12011-07-12 16:42:08 -0700318 public boolean wantsToBeVisible() {
319 return inAutoLogin()
Ben Murdochd51bb572011-08-17 20:42:02 +0100320 || (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
John Reckef654f12011-07-12 16:42:08 -0700321 && mSnapshotBar.isAnimating());
322 }
323
324 private boolean inAutoLogin() {
Ben Murdochd51bb572011-08-17 20:42:02 +0100325 return mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE;
John Reck0f602f32011-07-07 15:38:43 -0700326 }
327
328 public boolean isEditingUrl() {
329 return mNavBar.isEditingUrl();
330 }
331
332 public WebView getCurrentWebView() {
333 Tab t = mBaseUi.getActiveTab();
334 if (t != null) {
335 return t.getWebView();
336 } else {
337 return null;
338 }
339 }
340
341 public PageProgressView getProgressView() {
342 return mProgress;
343 }
344
345 public NavigationBarBase getNavigationBar() {
346 return mNavBar;
347 }
348
349 public boolean useQuickControls() {
350 return mUseQuickControls;
351 }
352
353 public boolean isInLoad() {
354 return mInLoad;
355 }
356
357 private ViewGroup.LayoutParams makeLayoutParams() {
358 if (mUseQuickControls) {
359 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
360 LayoutParams.WRAP_CONTENT);
361 } else {
362 return new AbsoluteLayout.LayoutParams(
363 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT,
364 0, 0);
365 }
366 }
367
368 @Override
369 public View focusSearch(View focused, int dir) {
370 if (FOCUS_DOWN == dir && hasFocus()) {
371 return getCurrentWebView();
372 }
373 return super.focusSearch(focused, dir);
374 }
375
John Reckef654f12011-07-12 16:42:08 -0700376 public void onTabDataChanged(Tab tab) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100377 if (mSnapshotBar != null) {
378 mSnapshotBar.onTabDataChanged(tab);
379 }
380
John Reckef654f12011-07-12 16:42:08 -0700381 if (tab.isSnapshot()) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100382 inflateSnapshotBar();
John Reckef654f12011-07-12 16:42:08 -0700383 mSnapshotBar.setVisibility(VISIBLE);
384 mNavBar.setVisibility(GONE);
385 } else {
Ben Murdochd51bb572011-08-17 20:42:02 +0100386 if (mSnapshotBar != null) {
387 mSnapshotBar.setVisibility(GONE);
388 }
John Reckef654f12011-07-12 16:42:08 -0700389 mNavBar.setVisibility(VISIBLE);
390 }
391 }
392
John Reck0f602f32011-07-07 15:38:43 -0700393}