1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.chrome.shell;
7 import android.content.Context;
8 import android.content.res.Configuration;
9 import android.graphics.drawable.ClipDrawable;
10 import android.util.AttributeSet;
11 import android.view.KeyEvent;
12 import android.view.MotionEvent;
13 import android.view.View;
14 import android.view.inputmethod.EditorInfo;
15 import android.view.inputmethod.InputMethodManager;
16 import android.widget.EditText;
17 import android.widget.ImageButton;
18 import android.widget.LinearLayout;
19 import android.widget.TextView;
20 import android.widget.TextView.OnEditorActionListener;
22 import org.chromium.base.ApiCompatibilityUtils;
23 import org.chromium.base.CommandLine;
24 import org.chromium.chrome.browser.EmptyTabObserver;
25 import org.chromium.chrome.browser.Tab;
26 import org.chromium.chrome.browser.TabObserver;
27 import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper;
28 import org.chromium.chrome.browser.appmenu.AppMenuHandler;
29 import org.chromium.chrome.shell.omnibox.SuggestionPopup;
30 import org.chromium.content.common.ContentSwitches;
33 * A Toolbar {@link View} that shows the URL and navigation buttons.
35 public class ChromeShellToolbar extends LinearLayout {
36 private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200;
38 private final Runnable mClearProgressRunnable = new Runnable() {
41 mProgressDrawable.setLevel(0);
45 private final Runnable mUpdateProgressRunnable = new Runnable() {
48 mProgressDrawable.setLevel(100 * mProgress);
50 mStopReloadButton.setImageResource(R.drawable.btn_stop_normal);
52 mStopReloadButton.setImageResource(R.drawable.btn_reload_normal);
53 ApiCompatibilityUtils.postOnAnimationDelayed(ChromeShellToolbar.this,
54 mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS);
59 private EditText mUrlTextView;
60 private ClipDrawable mProgressDrawable;
62 private ChromeShellTab mTab;
63 private final TabObserver mTabObserver;
65 private AppMenuHandler mMenuHandler;
66 private AppMenuButtonHelper mAppMenuButtonHelper;
68 private SuggestionPopup mSuggestionPopup;
70 private ImageButton mStopReloadButton;
71 private int mProgress = 0;
72 private boolean mLoading = true;
75 * @param context The Context the view is running in.
76 * @param attrs The attributes of the XML tag that is inflating the view.
78 public ChromeShellToolbar(Context context, AttributeSet attrs) {
79 super(context, attrs);
80 // When running performance benchmark, we don't want to observe the tab
81 // invalidation which would interfere with browser's processing content
82 // frame. See crbug.com/394976.
83 if (CommandLine.getInstance().hasSwitch(
84 ContentSwitches.RUNNING_PERFORMANCE_BENCHMARK)) {
85 mTabObserver = new EmptyTabObserver();
87 mTabObserver = new TabObserverImpl();
92 * The toolbar will visually represent the state of {@code tab}.
93 * @param tab The Tab that should be represented.
95 public void showTab(ChromeShellTab tab) {
96 if (mTab != null) mTab.removeObserver(mTabObserver);
98 mTab.addObserver(mTabObserver);
99 mUrlTextView.setText(mTab.getWebContents().getUrl());
102 private void onUpdateUrl(String url) {
103 mUrlTextView.setText(url);
106 private void onLoadProgressChanged(int progress) {
107 removeCallbacks(mClearProgressRunnable);
108 removeCallbacks(mUpdateProgressRunnable);
109 mProgress = progress;
110 mLoading = progress != 100;
111 ApiCompatibilityUtils.postOnAnimation(this, mUpdateProgressRunnable);
115 * Closes the suggestion popup.
117 public void hideSuggestions() {
118 if (mSuggestionPopup != null) mSuggestionPopup.hideSuggestions();
122 protected void onFinishInflate() {
123 super.onFinishInflate();
125 mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground();
126 initializeUrlField();
127 initializeMenuButton();
128 initializeStopReloadButton();
131 void setMenuHandler(AppMenuHandler menuHandler) {
132 mMenuHandler = menuHandler;
133 ImageButton menuButton = (ImageButton) findViewById(R.id.menu_button);
134 mAppMenuButtonHelper = new AppMenuButtonHelper(menuButton, mMenuHandler);
137 private void initializeUrlField() {
138 mUrlTextView = (EditText) findViewById(R.id.url);
139 mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
141 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
142 if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null ||
143 event.getKeyCode() != KeyEvent.KEYCODE_ENTER ||
144 event.getAction() != KeyEvent.ACTION_DOWN)) {
148 mTab.loadUrlWithSanitization(mUrlTextView.getText().toString());
149 mUrlTextView.clearFocus();
150 setKeyboardVisibilityForUrl(false);
151 mTab.getView().requestFocus();
155 mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
157 public void onFocusChange(View v, boolean hasFocus) {
158 setKeyboardVisibilityForUrl(hasFocus);
160 mUrlTextView.setText(mTab.getWebContents().getUrl());
161 mSuggestionPopup.dismissPopup();
165 mUrlTextView.setOnKeyListener(new OnKeyListener() {
167 public boolean onKey(View v, int keyCode, KeyEvent event) {
168 if (keyCode == KeyEvent.KEYCODE_BACK) {
169 mUrlTextView.clearFocus();
171 mTab.getView().requestFocus();
179 mSuggestionPopup = new SuggestionPopup(getContext(), mUrlTextView, this);
180 mUrlTextView.addTextChangedListener(mSuggestionPopup);
183 private void initializeMenuButton() {
184 ImageButton menuButton = (ImageButton) findViewById(R.id.menu_button);
185 menuButton.setOnClickListener(new OnClickListener() {
187 public void onClick(View view) {
188 if (mMenuHandler != null) mMenuHandler.showAppMenu(view, false, false);
191 menuButton.setOnTouchListener(new OnTouchListener() {
193 public boolean onTouch(View view, MotionEvent event) {
194 return mAppMenuButtonHelper != null && mAppMenuButtonHelper.onTouch(view, event);
199 private void initializeStopReloadButton() {
200 mStopReloadButton = (ImageButton) findViewById(R.id.stop_reload_button);
201 mStopReloadButton.setOnClickListener(new OnClickListener() {
203 public void onClick(View v) {
205 mTab.getWebContents().stop();
207 mTab.getWebContents().getNavigationController().reload(true);
214 * @return Current tab that is shown by ChromeShell.
216 public ChromeShellTab getCurrentTab() {
221 * Change the visibility of the software keyboard.
222 * @param visible Whether the keyboard should be shown or hidden.
224 public void setKeyboardVisibilityForUrl(boolean visible) {
225 InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
226 Context.INPUT_METHOD_SERVICE);
228 imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
230 imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
235 protected void onConfigurationChanged(Configuration newConfig) {
236 super.onConfigurationChanged(newConfig);
237 if (mMenuHandler != null) mMenuHandler.hideAppMenu();
240 private class TabObserverImpl extends EmptyTabObserver {
242 public void onLoadProgressChanged(Tab tab, int progress) {
243 if (tab == mTab) ChromeShellToolbar.this.onLoadProgressChanged(progress);
247 public void onUpdateUrl(Tab tab, String url) {
248 if (tab == mTab) ChromeShellToolbar.this.onUpdateUrl(url);