blob: a9da7c0e0be63eac425d3a6b030573f94b6dec3b [file] [log] [blame]
Leon Scroggins81db3662009-06-04 17:45:11 -04001/*
2 * Copyright (C) 2009 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.content.Context;
Leon Scroggins11e71b12010-01-25 10:40:38 -050020import android.content.Intent;
21import android.content.pm.PackageManager;
22import android.content.pm.ResolveInfo;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040023import android.content.res.Resources;
24import android.graphics.Bitmap;
25import android.graphics.Color;
Leon Scroggins1f005d32009-08-10 17:36:42 -040026import android.graphics.Rect;
Leon Scroggins62e8f942009-09-03 15:08:54 -040027import android.graphics.drawable.Animatable;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040028import android.graphics.drawable.BitmapDrawable;
Leon Scroggins81db3662009-06-04 17:45:11 -040029import android.graphics.drawable.Drawable;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040030import android.graphics.drawable.LayerDrawable;
31import android.graphics.drawable.PaintDrawable;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040032import android.os.Handler;
33import android.os.Message;
Leon Scroggins11e71b12010-01-25 10:40:38 -050034import android.speech.RecognizerIntent;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040035import android.util.TypedValue;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040036import android.view.ContextMenu;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040037import android.view.LayoutInflater;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040038import android.view.MenuInflater;
Leon Scroggins68579392009-09-15 15:31:54 -040039import android.view.MotionEvent;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040040import android.view.View;
Leon Scroggins68579392009-09-15 15:31:54 -040041import android.view.ViewConfiguration;
Leon Scroggins81db3662009-06-04 17:45:11 -040042import android.widget.ImageView;
43import android.widget.LinearLayout;
44import android.widget.ProgressBar;
45import android.widget.TextView;
Leon Scroggins81db3662009-06-04 17:45:11 -040046
Leon Scroggins1f005d32009-08-10 17:36:42 -040047/**
48 * This class represents a title bar for a particular "tab" or "window" in the
49 * browser.
50 */
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040051public class TitleBar extends LinearLayout {
Leon Scroggins81db3662009-06-04 17:45:11 -040052 private TextView mTitle;
Leon Scroggins1f005d32009-08-10 17:36:42 -040053 private Drawable mCloseDrawable;
54 private ImageView mRtButton;
Leon Scroggins62e8f942009-09-03 15:08:54 -040055 private Drawable mCircularProgress;
Leon Scroggins81db3662009-06-04 17:45:11 -040056 private ProgressBar mHorizontalProgress;
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -040057 private ImageView mFavicon;
Leon Scroggins62e8f942009-09-03 15:08:54 -040058 private ImageView mLockIcon;
Leon Scrogginsa81a7642009-08-31 17:05:41 -040059 private Drawable mStopDrawable;
60 private Drawable mBookmarkDrawable;
Leon Scroggins11e71b12010-01-25 10:40:38 -050061 private Drawable mVoiceDrawable;
Leon Scroggins81db3662009-06-04 17:45:11 -040062 private boolean mInLoad;
Leon Scrogginsa81a7642009-08-31 17:05:41 -040063 private BrowserActivity mBrowserActivity;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040064 private Drawable mGenericFavicon;
65 private int mIconDimension;
Leon Scroggins68579392009-09-15 15:31:54 -040066 private View mTitleBg;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040067 private MyHandler mHandler;
Leon Scroggins11e71b12010-01-25 10:40:38 -050068 private Intent mVoiceSearchIntent;
69 private boolean mInVoiceMode;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040070
71 private static int LONG_PRESS = 1;
Leon Scroggins81db3662009-06-04 17:45:11 -040072
Leon Scroggins68579392009-09-15 15:31:54 -040073 public TitleBar(BrowserActivity context) {
Leon Scroggins1f005d32009-08-10 17:36:42 -040074 super(context, null);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040075 mHandler = new MyHandler();
Leon Scroggins81db3662009-06-04 17:45:11 -040076 LayoutInflater factory = LayoutInflater.from(context);
77 factory.inflate(R.layout.title_bar, this);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040078 mBrowserActivity = context;
Leon Scroggins81db3662009-06-04 17:45:11 -040079
80 mTitle = (TextView) findViewById(R.id.title);
Leon Scrogginsa81a7642009-08-31 17:05:41 -040081 mTitle.setCompoundDrawablePadding(5);
Leon Scroggins81db3662009-06-04 17:45:11 -040082
Leon Scroggins68579392009-09-15 15:31:54 -040083 mTitleBg = findViewById(R.id.title_bg);
Leon Scroggins62e8f942009-09-03 15:08:54 -040084 mLockIcon = (ImageView) findViewById(R.id.lock);
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -040085 mFavicon = (ImageView) findViewById(R.id.favicon);
Leon Scroggins62e8f942009-09-03 15:08:54 -040086
Leon Scrogginsa81a7642009-08-31 17:05:41 -040087 mRtButton = (ImageView) findViewById(R.id.rt_btn);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040088 Resources resources = context.getResources();
89 mCircularProgress = (Drawable) resources.getDrawable(
Leon Scroggins62e8f942009-09-03 15:08:54 -040090 com.android.internal.R.drawable.search_spinner);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040091 mIconDimension = (int) TypedValue.applyDimension(
92 TypedValue.COMPLEX_UNIT_DIP, 20f,
93 resources.getDisplayMetrics());
94 mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
Leon Scroggins81db3662009-06-04 17:45:11 -040095 mHorizontalProgress = (ProgressBar) findViewById(
96 R.id.progress_horizontal);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040097 mGenericFavicon = context.getResources().getDrawable(
98 R.drawable.app_web_browser_sm);
Leon Scroggins11e71b12010-01-25 10:40:38 -050099 mVoiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
100 mVoiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
101 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
102 PackageManager pm = context.getPackageManager();
103 ResolveInfo ri = pm.resolveActivity(mVoiceSearchIntent,
104 PackageManager.MATCH_DEFAULT_ONLY);
105 if (ri == null) {
106 mVoiceSearchIntent = null;
107 } else {
108 mVoiceDrawable = resources.getDrawable(
109 android.R.drawable.ic_btn_speak_now);
110 }
111 mStopDrawable = resources.getDrawable(R.drawable.ic_btn_stop_v2);
112 mBookmarkDrawable = mRtButton.getDrawable();
Leon Scrogginse4b3bda2009-06-09 15:46:41 -0400113 }
114
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400115 private class MyHandler extends Handler {
116 public void handleMessage(Message msg) {
117 if (msg.what == LONG_PRESS) {
118 // Prevent the normal action from happening by setting the title
119 // bar's state to false.
120 mTitleBg.setPressed(false);
121 // Need to call a special method on BrowserActivity for when the
122 // fake title bar is up, because its ViewGroup does not show a
123 // context menu.
124 mBrowserActivity.showTitleBarContextMenu();
125 }
126 }
127 };
128
129 @Override
130 protected void onCreateContextMenu(ContextMenu menu) {
131 MenuInflater inflater = mBrowserActivity.getMenuInflater();
132 inflater.inflate(R.menu.title_context, menu);
133 }
134
Leon Scroggins68579392009-09-15 15:31:54 -0400135 @Override
136 public boolean onTouchEvent(MotionEvent event) {
137 switch (event.getAction()) {
138 case MotionEvent.ACTION_DOWN:
139 // Make all touches hit either the textfield or the button,
140 // depending on which side of the right edge of the textfield
141 // they hit.
142 if ((int) event.getX() > mTitleBg.getRight()) {
143 mRtButton.setPressed(true);
144 } else {
145 mTitleBg.setPressed(true);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400146 mHandler.sendMessageDelayed(mHandler.obtainMessage(
147 LONG_PRESS),
148 ViewConfiguration.getLongPressTimeout());
Leon Scroggins68579392009-09-15 15:31:54 -0400149 }
150 break;
151 case MotionEvent.ACTION_MOVE:
152 int slop = ViewConfiguration.get(mBrowserActivity)
153 .getScaledTouchSlop();
154 if ((int) event.getY() > getHeight() + slop) {
155 // We only trigger the actions in ACTION_UP if one or the
156 // other is pressed. Since the user moved off the title
157 // bar, mark both as not pressed.
158 mTitleBg.setPressed(false);
159 mRtButton.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400160 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400161 break;
162 }
163 int x = (int) event.getX();
164 int titleRight = mTitleBg.getRight();
165 if (mTitleBg.isPressed() && x > titleRight + slop) {
166 mTitleBg.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400167 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400168 } else if (mRtButton.isPressed() && x < titleRight - slop) {
169 mRtButton.setPressed(false);
170 }
171 break;
172 case MotionEvent.ACTION_CANCEL:
173 mRtButton.setPressed(false);
174 mTitleBg.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400175 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400176 break;
177 case MotionEvent.ACTION_UP:
178 if (mRtButton.isPressed()) {
Leon Scroggins11e71b12010-01-25 10:40:38 -0500179 if (mInVoiceMode) {
180 mBrowserActivity.startActivity(mVoiceSearchIntent);
181 } else if (mInLoad) {
Leon Scroggins68579392009-09-15 15:31:54 -0400182 mBrowserActivity.stopLoading();
183 } else {
184 mBrowserActivity.bookmarksOrHistoryPicker(false);
185 }
186 mRtButton.setPressed(false);
187 } else if (mTitleBg.isPressed()) {
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400188 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400189 mBrowserActivity.onSearchRequested();
190 mTitleBg.setPressed(false);
191 }
192 break;
193 default:
194 break;
195 }
196 return true;
Leon Scroggins81db3662009-06-04 17:45:11 -0400197 }
198
Leon Scroggins1f005d32009-08-10 17:36:42 -0400199 /**
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400200 * Set a new Bitmap for the Favicon.
Leon Scroggins1f005d32009-08-10 17:36:42 -0400201 */
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400202 /* package */ void setFavicon(Bitmap icon) {
203 Drawable[] array = new Drawable[3];
204 array[0] = new PaintDrawable(Color.BLACK);
205 PaintDrawable p = new PaintDrawable(Color.WHITE);
206 array[1] = p;
207 if (icon == null) {
208 array[2] = mGenericFavicon;
209 } else {
210 array[2] = new BitmapDrawable(icon);
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400211 }
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400212 LayerDrawable d = new LayerDrawable(array);
213 d.setLayerInset(1, 1, 1, 1, 1);
214 d.setLayerInset(2, 2, 2, 2, 2);
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400215 mFavicon.setImageDrawable(d);
Leon Scroggins81db3662009-06-04 17:45:11 -0400216 }
217
Leon Scroggins1f005d32009-08-10 17:36:42 -0400218 /**
Leon Scroggins11e71b12010-01-25 10:40:38 -0500219 * Change the TitleBar to or from voice mode. If there is no package to
220 * handle voice search, the TitleBar cannot be set to voice mode.
221 */
222 /* package */ void setInVoiceMode(boolean inVoiceMode) {
223 if (mInVoiceMode == inVoiceMode) return;
224 mInVoiceMode = inVoiceMode && mVoiceSearchIntent != null;
225 if (mInVoiceMode) {
226 mRtButton.setImageDrawable(mVoiceDrawable);
227 } else if (mInLoad) {
228 mRtButton.setImageDrawable(mStopDrawable);
229 } else {
230 mRtButton.setImageDrawable(mBookmarkDrawable);
231 }
232 }
233
234 /**
Leon Scroggins1f005d32009-08-10 17:36:42 -0400235 * Set the Drawable for the lock icon, or null to hide it.
236 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400237 /* package */ void setLock(Drawable d) {
Leon Scroggins62e8f942009-09-03 15:08:54 -0400238 if (null == d) {
239 mLockIcon.setVisibility(View.GONE);
240 } else {
241 mLockIcon.setImageDrawable(d);
242 mLockIcon.setVisibility(View.VISIBLE);
Leon Scroggins81db3662009-06-04 17:45:11 -0400243 }
244 }
245
Leon Scroggins1f005d32009-08-10 17:36:42 -0400246 /**
247 * Update the progress, from 0 to 100.
248 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400249 /* package */ void setProgress(int newProgress) {
Nicolas Roard1382b492009-09-16 21:50:06 +0100250 if (newProgress >= mHorizontalProgress.getMax()) {
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400251 mTitle.setCompoundDrawables(null, null, null, null);
Leon Scroggins62e8f942009-09-03 15:08:54 -0400252 ((Animatable) mCircularProgress).stop();
253 mHorizontalProgress.setVisibility(View.INVISIBLE);
Leon Scroggins11e71b12010-01-25 10:40:38 -0500254 if (!mInVoiceMode) {
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400255 mRtButton.setImageDrawable(mBookmarkDrawable);
Leon Scroggins1f005d32009-08-10 17:36:42 -0400256 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400257 mInLoad = false;
258 } else {
Leon Scroggins81db3662009-06-04 17:45:11 -0400259 mHorizontalProgress.setProgress(newProgress);
Nicolas Roard1382b492009-09-16 21:50:06 +0100260 if (!mInLoad && getWindowToken() != null) {
261 // checking the window token lets us be sure that we
262 // are attached to a window before starting the animation,
263 // preventing a potential race condition
264 // (fix for bug http://b/2115736)
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400265 mTitle.setCompoundDrawables(null, null, mCircularProgress,
Leon Scroggins62e8f942009-09-03 15:08:54 -0400266 null);
267 ((Animatable) mCircularProgress).start();
268 mHorizontalProgress.setVisibility(View.VISIBLE);
Leon Scroggins11e71b12010-01-25 10:40:38 -0500269 if (!mInVoiceMode) {
Leon Scroggins62e8f942009-09-03 15:08:54 -0400270 mRtButton.setImageDrawable(mStopDrawable);
271 }
272 mInLoad = true;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -0400273 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400274 }
275 }
276
Leon Scroggins1f005d32009-08-10 17:36:42 -0400277 /**
278 * Update the title and url.
279 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400280 /* package */ void setTitleAndUrl(CharSequence title, CharSequence url) {
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400281 if (url == null) {
282 mTitle.setText(R.string.title_bar_loading);
Leon Scrogginsd7c3dd52009-07-20 13:38:47 -0400283 } else {
Leon Scrogginsc62e9082009-09-03 10:20:44 -0400284 mTitle.setText(url.toString());
Leon Scrogginsd7c3dd52009-07-20 13:38:47 -0400285 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400286 }
287
288 /* package */ void setToTabPicker() {
289 mTitle.setText(R.string.tab_picker_title);
290 setFavicon(null);
291 setLock(null);
Leon Scroggins81db3662009-06-04 17:45:11 -0400292 mHorizontalProgress.setVisibility(View.GONE);
Leon Scroggins81db3662009-06-04 17:45:11 -0400293 }
294}