Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / android / shell / java / src / org / chromium / chrome / shell / ChromeShellToolbar.java
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.
4
5 package org.chromium.chrome.shell;
6
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;
21
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;
31
32 /**
33  * A Toolbar {@link View} that shows the URL and navigation buttons.
34  */
35 public class ChromeShellToolbar extends LinearLayout {
36     private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200;
37
38     private final Runnable mClearProgressRunnable = new Runnable() {
39         @Override
40         public void run() {
41             mProgressDrawable.setLevel(0);
42         }
43     };
44
45     private final Runnable mUpdateProgressRunnable = new Runnable() {
46         @Override
47         public void run() {
48             mProgressDrawable.setLevel(100 * mProgress);
49             if (mLoading) {
50                 mStopReloadButton.setImageResource(R.drawable.btn_stop_normal);
51             } else {
52                 mStopReloadButton.setImageResource(R.drawable.btn_reload_normal);
53                 ApiCompatibilityUtils.postOnAnimationDelayed(ChromeShellToolbar.this,
54                         mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS);
55             }
56         }
57     };
58
59     private EditText mUrlTextView;
60     private ClipDrawable mProgressDrawable;
61
62     private ChromeShellTab mTab;
63     private final TabObserver mTabObserver;
64
65     private AppMenuHandler mMenuHandler;
66     private AppMenuButtonHelper mAppMenuButtonHelper;
67
68     private SuggestionPopup mSuggestionPopup;
69
70     private ImageButton mStopReloadButton;
71     private int mProgress = 0;
72     private boolean mLoading = true;
73
74     /**
75      * @param context The Context the view is running in.
76      * @param attrs   The attributes of the XML tag that is inflating the view.
77      */
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();
86         } else {
87             mTabObserver = new TabObserverImpl();
88         }
89     }
90
91     /**
92      * The toolbar will visually represent the state of {@code tab}.
93      * @param tab The Tab that should be represented.
94      */
95     public void showTab(ChromeShellTab tab) {
96         if (mTab != null) mTab.removeObserver(mTabObserver);
97         mTab = tab;
98         mTab.addObserver(mTabObserver);
99         mUrlTextView.setText(mTab.getWebContents().getUrl());
100     }
101
102     private void onUpdateUrl(String url) {
103         mUrlTextView.setText(url);
104     }
105
106     private void onLoadProgressChanged(int progress) {
107         removeCallbacks(mClearProgressRunnable);
108         removeCallbacks(mUpdateProgressRunnable);
109         mProgress = progress;
110         mLoading = progress != 100;
111         ApiCompatibilityUtils.postOnAnimation(this, mUpdateProgressRunnable);
112     }
113
114     /**
115      * Closes the suggestion popup.
116      */
117     public void hideSuggestions() {
118         if (mSuggestionPopup != null) mSuggestionPopup.hideSuggestions();
119     }
120
121     @Override
122     protected void onFinishInflate() {
123         super.onFinishInflate();
124
125         mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground();
126         initializeUrlField();
127         initializeMenuButton();
128         initializeStopReloadButton();
129     }
130
131     void setMenuHandler(AppMenuHandler menuHandler) {
132         mMenuHandler = menuHandler;
133         ImageButton menuButton = (ImageButton) findViewById(R.id.menu_button);
134         mAppMenuButtonHelper = new AppMenuButtonHelper(menuButton, mMenuHandler);
135     }
136
137     private void initializeUrlField() {
138         mUrlTextView = (EditText) findViewById(R.id.url);
139         mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
140             @Override
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)) {
145                     return false;
146                 }
147
148                 mTab.loadUrlWithSanitization(mUrlTextView.getText().toString());
149                 mUrlTextView.clearFocus();
150                 setKeyboardVisibilityForUrl(false);
151                 mTab.getView().requestFocus();
152                 return true;
153             }
154         });
155         mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
156             @Override
157             public void onFocusChange(View v, boolean hasFocus) {
158                 setKeyboardVisibilityForUrl(hasFocus);
159                 if (!hasFocus) {
160                     mUrlTextView.setText(mTab.getWebContents().getUrl());
161                     mSuggestionPopup.dismissPopup();
162                 }
163             }
164         });
165         mUrlTextView.setOnKeyListener(new OnKeyListener() {
166             @Override
167             public boolean onKey(View v, int keyCode, KeyEvent event) {
168                 if (keyCode == KeyEvent.KEYCODE_BACK) {
169                     mUrlTextView.clearFocus();
170                     if (mTab != null) {
171                         mTab.getView().requestFocus();
172                     }
173                     return true;
174                 }
175                 return false;
176             }
177         });
178
179         mSuggestionPopup = new SuggestionPopup(getContext(), mUrlTextView, this);
180         mUrlTextView.addTextChangedListener(mSuggestionPopup);
181     }
182
183     private void initializeMenuButton() {
184         ImageButton menuButton = (ImageButton) findViewById(R.id.menu_button);
185         menuButton.setOnClickListener(new OnClickListener() {
186             @Override
187             public void onClick(View view) {
188                 if (mMenuHandler != null) mMenuHandler.showAppMenu(view, false, false);
189             }
190         });
191         menuButton.setOnTouchListener(new OnTouchListener() {
192             @Override
193             public boolean onTouch(View view, MotionEvent event) {
194                 return mAppMenuButtonHelper != null && mAppMenuButtonHelper.onTouch(view, event);
195             }
196         });
197     }
198
199     private void initializeStopReloadButton() {
200         mStopReloadButton = (ImageButton) findViewById(R.id.stop_reload_button);
201         mStopReloadButton.setOnClickListener(new OnClickListener() {
202             @Override
203             public void onClick(View v) {
204                 if (mLoading) {
205                     mTab.getWebContents().stop();
206                 } else {
207                     mTab.getWebContents().getNavigationController().reload(true);
208                 }
209             }
210         });
211     }
212
213     /**
214      * @return Current tab that is shown by ChromeShell.
215      */
216     public ChromeShellTab getCurrentTab() {
217         return mTab;
218     }
219
220     /**
221      * Change the visibility of the software keyboard.
222      * @param visible Whether the keyboard should be shown or hidden.
223      */
224     public void setKeyboardVisibilityForUrl(boolean visible) {
225         InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
226                 Context.INPUT_METHOD_SERVICE);
227         if (visible) {
228             imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
229         } else {
230             imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
231         }
232     }
233
234     @Override
235     protected void onConfigurationChanged(Configuration newConfig) {
236         super.onConfigurationChanged(newConfig);
237         if (mMenuHandler != null) mMenuHandler.hideAppMenu();
238     }
239
240     private class TabObserverImpl extends EmptyTabObserver {
241         @Override
242         public void onLoadProgressChanged(Tab tab, int progress) {
243             if (tab == mTab) ChromeShellToolbar.this.onLoadProgressChanged(progress);
244         }
245
246         @Override
247         public void onUpdateUrl(Tab tab, String url) {
248             if (tab == mTab) ChromeShellToolbar.this.onUpdateUrl(url);
249         }
250     }
251 }