michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko; michael@0: michael@0: import org.mozilla.gecko.util.GeckoEventListener; michael@0: import org.mozilla.gecko.util.ThreadUtils; michael@0: michael@0: import org.json.JSONObject; michael@0: michael@0: import android.content.Context; michael@0: import android.text.Editable; michael@0: import android.text.TextUtils; michael@0: import android.text.TextWatcher; michael@0: import android.util.AttributeSet; michael@0: import android.view.KeyEvent; michael@0: import android.view.LayoutInflater; michael@0: import android.view.View; michael@0: import android.view.inputmethod.InputMethodManager; michael@0: import android.widget.LinearLayout; michael@0: michael@0: public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnClickListener, GeckoEventListener { michael@0: private static final String REQUEST_ID = "FindInPageBar"; michael@0: michael@0: private final Context mContext; michael@0: private CustomEditText mFindText; michael@0: private boolean mInflated = false; michael@0: michael@0: public FindInPageBar(Context context, AttributeSet attrs) { michael@0: super(context, attrs); michael@0: mContext = context; michael@0: setFocusable(true); michael@0: } michael@0: michael@0: public void inflateContent() { michael@0: LayoutInflater inflater = LayoutInflater.from(mContext); michael@0: View content = inflater.inflate(R.layout.find_in_page_content, this); michael@0: michael@0: content.findViewById(R.id.find_prev).setOnClickListener(this); michael@0: content.findViewById(R.id.find_next).setOnClickListener(this); michael@0: content.findViewById(R.id.find_close).setOnClickListener(this); michael@0: michael@0: // Capture clicks on the rest of the view to prevent them from michael@0: // leaking into other views positioned below. michael@0: content.setOnClickListener(this); michael@0: michael@0: mFindText = (CustomEditText) content.findViewById(R.id.find_text); michael@0: mFindText.addTextChangedListener(this); michael@0: mFindText.setOnKeyPreImeListener(new CustomEditText.OnKeyPreImeListener() { michael@0: @Override michael@0: public boolean onKeyPreIme(View v, int keyCode, KeyEvent event) { michael@0: if (keyCode == KeyEvent.KEYCODE_BACK) { michael@0: hide(); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: }); michael@0: michael@0: mInflated = true; michael@0: GeckoAppShell.getEventDispatcher().registerEventListener("TextSelection:Data", this); michael@0: } michael@0: michael@0: public void show() { michael@0: if (!mInflated) michael@0: inflateContent(); michael@0: michael@0: setVisibility(VISIBLE); michael@0: mFindText.requestFocus(); michael@0: michael@0: // handleMessage() receives response message and determines initial state of softInput michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("TextSelection:Get", REQUEST_ID)); michael@0: } michael@0: michael@0: public void hide() { michael@0: setVisibility(GONE); michael@0: getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0); michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Closed", null)); michael@0: } michael@0: michael@0: private InputMethodManager getInputMethodManager(View view) { michael@0: Context context = view.getContext(); michael@0: return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); michael@0: } michael@0: michael@0: public void onDestroy() { michael@0: if (!mInflated) { michael@0: return; michael@0: } michael@0: GeckoAppShell.getEventDispatcher().unregisterEventListener("TextSelection:Data", this); michael@0: } michael@0: michael@0: // TextWatcher implementation michael@0: michael@0: @Override michael@0: public void afterTextChanged(Editable s) { michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Find", s.toString())); michael@0: } michael@0: michael@0: @Override michael@0: public void beforeTextChanged(CharSequence s, int start, int count, int after) { michael@0: // ignore michael@0: } michael@0: michael@0: @Override michael@0: public void onTextChanged(CharSequence s, int start, int before, int count) { michael@0: // ignore michael@0: } michael@0: michael@0: // View.OnClickListener implementation michael@0: michael@0: @Override michael@0: public void onClick(View v) { michael@0: final int viewId = v.getId(); michael@0: michael@0: if (viewId == R.id.find_prev) { michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Prev", mFindText.getText().toString())); michael@0: getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0); michael@0: return; michael@0: } michael@0: michael@0: if (viewId == R.id.find_next) { michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Next", mFindText.getText().toString())); michael@0: getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0); michael@0: return; michael@0: } michael@0: michael@0: if (viewId == R.id.find_close) { michael@0: hide(); michael@0: } michael@0: } michael@0: michael@0: // GeckoEventListener implementation michael@0: michael@0: @Override michael@0: public void handleMessage(String event, JSONObject message) { michael@0: if (!event.equals("TextSelection:Data") || !REQUEST_ID.equals(message.optString("requestId"))) { michael@0: return; michael@0: } michael@0: michael@0: final String text = message.optString("text"); michael@0: michael@0: // Populate an initial find string, virtual keyboard not required. michael@0: if (!TextUtils.isEmpty(text)) { michael@0: // Populate initial selection michael@0: ThreadUtils.postToUiThread(new Runnable() { michael@0: @Override michael@0: public void run() { michael@0: mFindText.setText(text); michael@0: } michael@0: }); michael@0: return; michael@0: } michael@0: michael@0: // Show the virtual keyboard. michael@0: if (mFindText.hasWindowFocus()) { michael@0: getInputMethodManager(mFindText).showSoftInput(mFindText, 0); michael@0: } else { michael@0: // showSoftInput won't work until after the window is focused. michael@0: mFindText.setOnWindowFocusChangeListener(new CustomEditText.OnWindowFocusChangeListener() { michael@0: @Override michael@0: public void onWindowFocusChanged(boolean hasFocus) { michael@0: if (!hasFocus) michael@0: return; michael@0: michael@0: mFindText.setOnWindowFocusChangeListener(null); michael@0: getInputMethodManager(mFindText).showSoftInput(mFindText, 0); michael@0: } michael@0: }); michael@0: } michael@0: } michael@0: }