blob: 23b1ed50552a7f2ea135c4536d3f7ee1993961ac [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 Scroggins3bbb6ca2009-09-09 12:51:10 -040020import android.content.res.Resources;
21import android.graphics.Bitmap;
22import android.graphics.Color;
Leon Scroggins1f005d32009-08-10 17:36:42 -040023import android.graphics.Rect;
Leon Scroggins62e8f942009-09-03 15:08:54 -040024import android.graphics.drawable.Animatable;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040025import android.graphics.drawable.BitmapDrawable;
Leon Scroggins81db3662009-06-04 17:45:11 -040026import android.graphics.drawable.Drawable;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040027import android.graphics.drawable.LayerDrawable;
28import android.graphics.drawable.PaintDrawable;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040029import android.os.Handler;
30import android.os.Message;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040031import android.util.TypedValue;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040032import android.view.ContextMenu;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040033import android.view.LayoutInflater;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040034import android.view.MenuInflater;
Leon Scroggins68579392009-09-15 15:31:54 -040035import android.view.MotionEvent;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040036import android.view.View;
Leon Scroggins68579392009-09-15 15:31:54 -040037import android.view.ViewConfiguration;
Leon Scroggins81db3662009-06-04 17:45:11 -040038import android.widget.ImageView;
39import android.widget.LinearLayout;
40import android.widget.ProgressBar;
41import android.widget.TextView;
Leon Scroggins81db3662009-06-04 17:45:11 -040042
Leon Scroggins1f005d32009-08-10 17:36:42 -040043/**
44 * This class represents a title bar for a particular "tab" or "window" in the
45 * browser.
46 */
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040047public class TitleBar extends LinearLayout {
Leon Scroggins81db3662009-06-04 17:45:11 -040048 private TextView mTitle;
Leon Scroggins1f005d32009-08-10 17:36:42 -040049 private Drawable mCloseDrawable;
50 private ImageView mRtButton;
Leon Scroggins62e8f942009-09-03 15:08:54 -040051 private Drawable mCircularProgress;
Leon Scroggins81db3662009-06-04 17:45:11 -040052 private ProgressBar mHorizontalProgress;
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -040053 private ImageView mFavicon;
Leon Scroggins62e8f942009-09-03 15:08:54 -040054 private ImageView mLockIcon;
Leon Scrogginsa81a7642009-08-31 17:05:41 -040055 private Drawable mStopDrawable;
56 private Drawable mBookmarkDrawable;
Leon Scroggins81db3662009-06-04 17:45:11 -040057 private boolean mInLoad;
Leon Scrogginsa81a7642009-08-31 17:05:41 -040058 private BrowserActivity mBrowserActivity;
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040059 private Drawable mGenericFavicon;
60 private int mIconDimension;
Leon Scroggins68579392009-09-15 15:31:54 -040061 private View mTitleBg;
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040062 private MyHandler mHandler;
63
64 private static int LONG_PRESS = 1;
Leon Scroggins81db3662009-06-04 17:45:11 -040065
Leon Scroggins68579392009-09-15 15:31:54 -040066 public TitleBar(BrowserActivity context) {
Leon Scroggins1f005d32009-08-10 17:36:42 -040067 super(context, null);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040068 mHandler = new MyHandler();
Leon Scroggins81db3662009-06-04 17:45:11 -040069 LayoutInflater factory = LayoutInflater.from(context);
70 factory.inflate(R.layout.title_bar, this);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040071 mBrowserActivity = context;
Leon Scroggins81db3662009-06-04 17:45:11 -040072
73 mTitle = (TextView) findViewById(R.id.title);
Leon Scrogginsa81a7642009-08-31 17:05:41 -040074 mTitle.setCompoundDrawablePadding(5);
Leon Scroggins81db3662009-06-04 17:45:11 -040075
Leon Scroggins68579392009-09-15 15:31:54 -040076 mTitleBg = findViewById(R.id.title_bg);
Leon Scroggins62e8f942009-09-03 15:08:54 -040077 mLockIcon = (ImageView) findViewById(R.id.lock);
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -040078 mFavicon = (ImageView) findViewById(R.id.favicon);
Leon Scroggins62e8f942009-09-03 15:08:54 -040079
Leon Scrogginsa81a7642009-08-31 17:05:41 -040080 mRtButton = (ImageView) findViewById(R.id.rt_btn);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040081 Resources resources = context.getResources();
82 mCircularProgress = (Drawable) resources.getDrawable(
Leon Scroggins62e8f942009-09-03 15:08:54 -040083 com.android.internal.R.drawable.search_spinner);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040084 mIconDimension = (int) TypedValue.applyDimension(
85 TypedValue.COMPLEX_UNIT_DIP, 20f,
86 resources.getDisplayMetrics());
87 mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
Leon Scroggins81db3662009-06-04 17:45:11 -040088 mHorizontalProgress = (ProgressBar) findViewById(
89 R.id.progress_horizontal);
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -040090 mGenericFavicon = context.getResources().getDrawable(
91 R.drawable.app_web_browser_sm);
Leon Scrogginse4b3bda2009-06-09 15:46:41 -040092 }
93
Leon Scrogginsc6fa1102009-09-21 10:40:01 -040094 private class MyHandler extends Handler {
95 public void handleMessage(Message msg) {
96 if (msg.what == LONG_PRESS) {
97 // Prevent the normal action from happening by setting the title
98 // bar's state to false.
99 mTitleBg.setPressed(false);
100 // Need to call a special method on BrowserActivity for when the
101 // fake title bar is up, because its ViewGroup does not show a
102 // context menu.
103 mBrowserActivity.showTitleBarContextMenu();
104 }
105 }
106 };
107
108 @Override
109 protected void onCreateContextMenu(ContextMenu menu) {
110 MenuInflater inflater = mBrowserActivity.getMenuInflater();
111 inflater.inflate(R.menu.title_context, menu);
112 }
113
Leon Scroggins68579392009-09-15 15:31:54 -0400114 @Override
115 public boolean onTouchEvent(MotionEvent event) {
116 switch (event.getAction()) {
117 case MotionEvent.ACTION_DOWN:
118 // Make all touches hit either the textfield or the button,
119 // depending on which side of the right edge of the textfield
120 // they hit.
121 if ((int) event.getX() > mTitleBg.getRight()) {
122 mRtButton.setPressed(true);
123 } else {
124 mTitleBg.setPressed(true);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400125 mHandler.sendMessageDelayed(mHandler.obtainMessage(
126 LONG_PRESS),
127 ViewConfiguration.getLongPressTimeout());
Leon Scroggins68579392009-09-15 15:31:54 -0400128 }
129 break;
130 case MotionEvent.ACTION_MOVE:
131 int slop = ViewConfiguration.get(mBrowserActivity)
132 .getScaledTouchSlop();
133 if ((int) event.getY() > getHeight() + slop) {
134 // We only trigger the actions in ACTION_UP if one or the
135 // other is pressed. Since the user moved off the title
136 // bar, mark both as not pressed.
137 mTitleBg.setPressed(false);
138 mRtButton.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400139 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400140 break;
141 }
142 int x = (int) event.getX();
143 int titleRight = mTitleBg.getRight();
144 if (mTitleBg.isPressed() && x > titleRight + slop) {
145 mTitleBg.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400146 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400147 } else if (mRtButton.isPressed() && x < titleRight - slop) {
148 mRtButton.setPressed(false);
149 }
150 break;
151 case MotionEvent.ACTION_CANCEL:
152 mRtButton.setPressed(false);
153 mTitleBg.setPressed(false);
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400154 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400155 break;
156 case MotionEvent.ACTION_UP:
157 if (mRtButton.isPressed()) {
158 if (mInLoad) {
159 mBrowserActivity.stopLoading();
160 } else {
161 mBrowserActivity.bookmarksOrHistoryPicker(false);
162 }
163 mRtButton.setPressed(false);
164 } else if (mTitleBg.isPressed()) {
Leon Scrogginsc6fa1102009-09-21 10:40:01 -0400165 mHandler.removeMessages(LONG_PRESS);
Leon Scroggins68579392009-09-15 15:31:54 -0400166 mBrowserActivity.onSearchRequested();
167 mTitleBg.setPressed(false);
168 }
169 break;
170 default:
171 break;
172 }
173 return true;
Leon Scroggins81db3662009-06-04 17:45:11 -0400174 }
175
Leon Scroggins1f005d32009-08-10 17:36:42 -0400176 /**
Leon Scroggins1f005d32009-08-10 17:36:42 -0400177 * Return whether the associated WebView is currently loading. Needed to
178 * determine whether a click should stop the load or close the tab.
179 */
180 /* package */ boolean isInLoad() {
181 return mInLoad;
182 }
183
184 /**
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400185 * Set a new Bitmap for the Favicon.
Leon Scroggins1f005d32009-08-10 17:36:42 -0400186 */
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400187 /* package */ void setFavicon(Bitmap icon) {
188 Drawable[] array = new Drawable[3];
189 array[0] = new PaintDrawable(Color.BLACK);
190 PaintDrawable p = new PaintDrawable(Color.WHITE);
191 array[1] = p;
192 if (icon == null) {
193 array[2] = mGenericFavicon;
194 } else {
195 array[2] = new BitmapDrawable(icon);
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400196 }
Leon Scroggins3bbb6ca2009-09-09 12:51:10 -0400197 LayerDrawable d = new LayerDrawable(array);
198 d.setLayerInset(1, 1, 1, 1, 1);
199 d.setLayerInset(2, 2, 2, 2, 2);
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400200 mFavicon.setImageDrawable(d);
Leon Scroggins81db3662009-06-04 17:45:11 -0400201 }
202
Leon Scroggins1f005d32009-08-10 17:36:42 -0400203 /**
204 * Set the Drawable for the lock icon, or null to hide it.
205 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400206 /* package */ void setLock(Drawable d) {
Leon Scroggins62e8f942009-09-03 15:08:54 -0400207 if (null == d) {
208 mLockIcon.setVisibility(View.GONE);
209 } else {
210 mLockIcon.setImageDrawable(d);
211 mLockIcon.setVisibility(View.VISIBLE);
Leon Scroggins81db3662009-06-04 17:45:11 -0400212 }
213 }
214
Leon Scroggins1f005d32009-08-10 17:36:42 -0400215 /**
216 * Update the progress, from 0 to 100.
217 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400218 /* package */ void setProgress(int newProgress) {
Nicolas Roard1382b492009-09-16 21:50:06 +0100219 if (newProgress >= mHorizontalProgress.getMax()) {
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400220 mTitle.setCompoundDrawables(null, null, null, null);
Leon Scroggins62e8f942009-09-03 15:08:54 -0400221 ((Animatable) mCircularProgress).stop();
222 mHorizontalProgress.setVisibility(View.INVISIBLE);
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400223 if (mBookmarkDrawable != null) {
224 mRtButton.setImageDrawable(mBookmarkDrawable);
Leon Scroggins1f005d32009-08-10 17:36:42 -0400225 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400226 mInLoad = false;
227 } else {
Leon Scroggins81db3662009-06-04 17:45:11 -0400228 mHorizontalProgress.setProgress(newProgress);
Nicolas Roard1382b492009-09-16 21:50:06 +0100229 if (!mInLoad && getWindowToken() != null) {
230 // checking the window token lets us be sure that we
231 // are attached to a window before starting the animation,
232 // preventing a potential race condition
233 // (fix for bug http://b/2115736)
Leon Scrogginsf4bb18a2009-09-11 18:37:53 -0400234 mTitle.setCompoundDrawables(null, null, mCircularProgress,
Leon Scroggins62e8f942009-09-03 15:08:54 -0400235 null);
236 ((Animatable) mCircularProgress).start();
237 mHorizontalProgress.setVisibility(View.VISIBLE);
238 if (mBookmarkDrawable == null) {
239 mBookmarkDrawable = mRtButton.getDrawable();
240 }
241 if (mStopDrawable == null) {
Leon Scrogginscfe35d92009-09-30 15:29:45 -0400242 mRtButton.setImageResource(R.drawable.ic_btn_stop_v2);
Leon Scroggins62e8f942009-09-03 15:08:54 -0400243 mStopDrawable = mRtButton.getDrawable();
244 } else {
245 mRtButton.setImageDrawable(mStopDrawable);
246 }
247 mInLoad = true;
Leon Scrogginse4b3bda2009-06-09 15:46:41 -0400248 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400249 }
250 }
251
Leon Scroggins1f005d32009-08-10 17:36:42 -0400252 /**
253 * Update the title and url.
254 */
Leon Scroggins81db3662009-06-04 17:45:11 -0400255 /* package */ void setTitleAndUrl(CharSequence title, CharSequence url) {
Leon Scrogginsa81a7642009-08-31 17:05:41 -0400256 if (url == null) {
257 mTitle.setText(R.string.title_bar_loading);
Leon Scrogginsd7c3dd52009-07-20 13:38:47 -0400258 } else {
Leon Scrogginsc62e9082009-09-03 10:20:44 -0400259 mTitle.setText(url.toString());
Leon Scrogginsd7c3dd52009-07-20 13:38:47 -0400260 }
Leon Scroggins81db3662009-06-04 17:45:11 -0400261 }
262
263 /* package */ void setToTabPicker() {
264 mTitle.setText(R.string.tab_picker_title);
265 setFavicon(null);
266 setLock(null);
Leon Scroggins81db3662009-06-04 17:45:11 -0400267 mHorizontalProgress.setVisibility(View.GONE);
Leon Scroggins81db3662009-06-04 17:45:11 -0400268 }
269}