Bug 695172 - Find in page. r=mfinkle

This commit is contained in:
Margaret Leibovic 2012-05-30 13:26:13 -07:00
parent d07ccd8c16
commit f9950f4015
21 changed files with 313 additions and 3 deletions

View File

@ -0,0 +1,106 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import android.content.Context;
import android.content.res.Resources;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
public class FindInPageBar extends RelativeLayout implements TextWatcher, View.OnClickListener {
private static final String LOGTAG = "GeckoFindInPagePopup";
private final Context mContext;
private EditText mFindText;
private boolean mInflated = false;
public FindInPageBar(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setFocusable(true);
}
public void inflateContent() {
LayoutInflater inflater = LayoutInflater.from(mContext);
View content = inflater.inflate(R.layout.find_in_page_content, this);
content.findViewById(R.id.find_prev).setOnClickListener(this);
content.findViewById(R.id.find_next).setOnClickListener(this);
content.findViewById(R.id.find_close).setOnClickListener(this);
mFindText = (EditText) content.findViewById(R.id.find_text);
mFindText.addTextChangedListener(this);
// EditText styling modeled after AwesomeBar styling
int padding[] = { mFindText.getPaddingLeft(),
mFindText.getPaddingTop(),
mFindText.getPaddingRight(),
mFindText.getPaddingBottom() };
Resources resources = getContext().getResources();
GeckoStateListDrawable states = new GeckoStateListDrawable();
states.initializeFilter(GeckoApp.mBrowserToolbar.getHighlightColor());
states.addState(new int[] { android.R.attr.state_focused }, resources.getDrawable(R.drawable.address_bar_url_pressed));
states.addState(new int[] { android.R.attr.state_pressed }, resources.getDrawable(R.drawable.address_bar_url_pressed));
states.addState(new int[] { }, resources.getDrawable(R.drawable.address_bar_url_default));
mFindText.setBackgroundDrawable(states);
mFindText.setPadding(padding[0], padding[1], padding[2], padding[3]);
mInflated = true;
}
public void show() {
if (!mInflated)
inflateContent();
setVisibility(VISIBLE);
mFindText.requestFocus();
}
public void hide() {
setVisibility(GONE);
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Closed", null));
}
// TextWatcher implementation
public void afterTextChanged(Editable s) {
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Find", s.toString()));
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// ignore
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// ignore
}
// View.OnClickListener implementation
public void onClick(View v) {
switch (v.getId()) {
case R.id.find_prev:
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Prev", mFindText.getText().toString()));
break;
case R.id.find_next:
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Next", mFindText.getText().toString()));
break;
case R.id.find_close:
hide();
break;
}
}
}

View File

@ -108,6 +108,7 @@ abstract public class GeckoApp
private static GeckoLayerClient mLayerClient;
private AboutHomeContent mAboutHomeContent;
private static AbsoluteLayout mPluginContainer;
private static FindInPageBar mFindInPageBar;
private View mFullScreenPluginView;
@ -407,15 +408,17 @@ abstract public class GeckoApp
MenuItem share = aMenu.findItem(R.id.share);
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
MenuItem charEncoding = aMenu.findItem(R.id.char_encoding);
MenuItem findInPage = aMenu.findItem(R.id.find_in_page);
if (tab == null || tab.getURL() == null) {
bookmark.setEnabled(false);
forward.setEnabled(false);
share.setEnabled(false);
saveAsPDF.setEnabled(false);
findInPage.setEnabled(false);
return true;
}
bookmark.setEnabled(true);
bookmark.setCheckable(true);
@ -438,6 +441,10 @@ abstract public class GeckoApp
saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
// Disable find in page for about:home, since it won't work on Java content
if (!tab.getURL().equals("about:home"))
findInPage.setEnabled(true);
charEncoding.setVisible(GeckoPreferences.getCharEncodingState());
return true;
@ -512,6 +519,9 @@ abstract public class GeckoApp
case R.id.char_encoding:
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("CharEncoding:Get", null));
return true;
case R.id.find_in_page:
mFindInPageBar.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
@ -1782,6 +1792,7 @@ abstract public class GeckoApp
}
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
mDoorHangerPopup = new DoorHangerPopup(this);
mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);

View File

@ -52,6 +52,8 @@ public final class GeckoViewsFactory implements LayoutInflater.Factory {
return new FormAssistPopup(context, attrs);
else if (TextUtils.equals(viewName, "LinkTextView"))
return new LinkTextView(context, attrs);
else if (TextUtils.equals(viewName, "FindInPageBar"))
return new FindInPageBar(context, attrs);
}
return null;

View File

@ -57,6 +57,7 @@ FENNEC_JAVA_FILES = \
DoorHanger.java \
DoorHangerPopup.java \
Favicons.java \
FindInPageBar.java \
FloatUtils.java \
FormAssistPopup.java \
GeckoActionBar.java \
@ -254,6 +255,7 @@ RES_LAYOUT = \
res/layout/browser_toolbar.xml \
res/layout/doorhangerpopup.xml \
res/layout/doorhanger.xml \
res/layout/find_in_page_content.xml \
res/layout/gecko_app.xml \
res/layout/launch_app_list.xml \
res/layout/launch_app_listitem.xml \
@ -394,6 +396,10 @@ RES_DRAWABLE_BASE = \
res/drawable/doorhanger_bg.9.png \
res/drawable/doorhanger_shadow_bg.9.png \
res/drawable/doorhanger_popup_bg.9.png \
res/drawable/find_close.png \
res/drawable/find_next.png \
res/drawable/find_prev.png \
res/drawable/larry_green.png \
res/drawable/larry_blue.png \
res/drawable/larry_green.png \
res/drawable/site_security_identified.png \
@ -457,6 +463,9 @@ RES_DRAWABLE_HDPI = \
res/drawable-hdpi/doorhanger_bg.9.png \
res/drawable-hdpi/doorhanger_shadow_bg.9.png \
res/drawable-hdpi/doorhanger_popup_bg.9.png \
res/drawable-hdpi/find_close.png \
res/drawable-hdpi/find_next.png \
res/drawable-hdpi/find_prev.png \
res/drawable-hdpi/larry_blue.png \
res/drawable-hdpi/larry_green.png \
res/drawable-hdpi/site_security_identified.png \
@ -543,6 +552,9 @@ RES_DRAWABLE_XHDPI_V11 = \
res/drawable-xhdpi-v11/doorhanger_bg.9.png \
res/drawable-xhdpi-v11/doorhanger_shadow_bg.9.png \
res/drawable-xhdpi-v11/doorhanger_popup_bg.9.png \
res/drawable-xhdpi-v11/find_close.png \
res/drawable-xhdpi-v11/find_next.png \
res/drawable-xhdpi-v11/find_prev.png \
res/drawable-xhdpi-v11/urlbar_stop.png \
res/drawable-xhdpi-v11/larry_blue.png \
res/drawable-xhdpi-v11/larry_green.png \

View File

@ -94,6 +94,14 @@
<!ENTITY share "Share">
<!ENTITY share_title "Share via">
<!ENTITY save_as_pdf "Save as PDF">
<!ENTITY find_in_page "Find in Page">
<!-- Localization note (find_text, find_prev, find_next, find_close) : These strings are used
as alternate text for accessibility. They are not visible in the UI. -->
<!ENTITY find_text "Find in Page">
<!ENTITY find_prev "Previous">
<!ENTITY find_next "Next">
<!ENTITY find_close "Close">
<!ENTITY contextmenu_open_new_tab "Open in New Tab">
<!ENTITY contextmenu_remove_history "Remove">

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -27,6 +27,10 @@
android:layout_height="fill_parent"
android:background="@drawable/abouthome_bg_repeat"/>
</RelativeLayout>
</RelativeLayout>
<org.mozilla.gecko.FindInPageBar android:id="@+id/find_in_page"
style="@style/FindBar"
visibility="gone"/>
</LinearLayout>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<EditText android:id="@+id/find_text"
android:contentDescription="@string/find_text"
android:singleLine="true"
android:textColor="#000000"
android:inputType="text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:paddingLeft="15dip"
android:paddingRight="15dip"
android:imeOptions="actionSearch"
android:selectAllOnFocus="true"
android:gravity="center_vertical|left"
android:layout_toLeftOf="@+id/find_prev"/>
<ImageButton android:id="@+id/find_prev"
style="@style/FindBar.ImageButton"
android:contentDescription="@string/find_prev"
android:src="@drawable/find_prev"
android:layout_toLeftOf="@+id/find_next"/>
<ImageButton android:id="@+id/find_next"
style="@style/FindBar.ImageButton"
android:contentDescription="@string/find_next"
android:src="@drawable/find_next"
android:layout_toLeftOf="@+id/find_close"/>
<ImageButton android:id="@+id/find_close"
style="@style/FindBar.ImageButton"
android:contentDescription="@string/find_close"
android:src="@drawable/find_close"
android:layout_alignParentRight="true"/>
</merge>

View File

@ -29,6 +29,10 @@
android:layout_height="fill_parent"
android:background="@drawable/abouthome_bg_repeat"/>
</RelativeLayout>
</RelativeLayout>
<org.mozilla.gecko.FindInPageBar android:id="@+id/find_in_page"
style="@style/FindBar"
visibility="gone"/>
</LinearLayout>

View File

@ -25,6 +25,9 @@
android:icon="@drawable/ic_menu_save_as_pdf"
android:title="@string/save_as_pdf" />
<item android:id="@+id/find_in_page"
android:title="@string/find_in_page" />
<item android:id="@+id/site_settings"
android:title="@string/site_settings_title" />

View File

@ -97,4 +97,27 @@
<item name="android:background">@drawable/tabs_tray_bg_repeat</item>
</style>
<!-- Find bar -->
<style name="FindBar">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:orientation">horizontal</item>
<item name="android:background">#000000</item>
<item name="android:paddingLeft">3dip</item>
<item name="android:paddingRight">3dip</item>
<item name="android:paddingTop">6dip</item>
<item name="android:paddingBottom">6dip</item>
</style>
<!-- Find bar - Image Button -->
<style name="FindBar.ImageButton">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">5dip</item>
<item name="android:layout_marginRight">5dip</item>
<item name="android:scaleType">fitCenter</item>
<item name="android:layout_centerVertical">true</item>
<item name="android:background">@android:color/transparent</item>
</style>
</resources>

View File

@ -57,6 +57,12 @@
<string name="share">&share;</string>
<string name="share_title">&share_title;</string>
<string name="save_as_pdf">&save_as_pdf;</string>
<string name="find_in_page">&find_in_page;</string>
<string name="find_text">&find_text;</string>
<string name="find_prev">&find_prev;</string>
<string name="find_next">&find_next;</string>
<string name="find_close">&find_close;</string>
<string name="settings">&settings;</string>
<string name="settings_title">&settings_title;</string>

View File

@ -191,6 +191,7 @@ var BrowserApp = {
NativeWindow.init();
Downloads.init();
FindHelper.init();
FormAssistant.init();
OfflineApps.init();
IndexedDB.init();
@ -392,6 +393,7 @@ var BrowserApp = {
shutdown: function shutdown() {
NativeWindow.uninit();
FormAssistant.uninit();
FindHelper.uninit();
OfflineApps.uninit();
IndexedDB.uninit();
ViewportHandler.uninit();
@ -3176,6 +3178,97 @@ var ErrorPageEventHandler = {
}
};
var FindHelper = {
_find: null,
_findInProgress: false,
_targetTab: null,
_initialViewport: null,
_viewportChanged: false,
init: function() {
Services.obs.addObserver(this, "FindInPage:Find", false);
Services.obs.addObserver(this, "FindInPage:Prev", false);
Services.obs.addObserver(this, "FindInPage:Next", false);
Services.obs.addObserver(this, "FindInPage:Closed", false);
},
uninit: function() {
Services.obs.removeObserver(this, "FindInPage:Find", false);
Services.obs.removeObserver(this, "FindInPage:Prev", false);
Services.obs.removeObserver(this, "FindInPage:Next", false);
Services.obs.removeObserver(this, "FindInPage:Closed", false);
},
observe: function(aMessage, aTopic, aData) {
switch(aTopic) {
case "FindInPage:Find":
this.doFind(aData);
break;
case "FindInPage:Prev":
this.findAgain(aData, true);
break;
case "FindInPage:Next":
this.findAgain(aData, false);
break;
case "FindInPage:Closed":
this.findClosed();
break;
}
},
doFind: function(aSearchString) {
if (!this._findInProgress) {
this._findInProgress = true;
this._targetTab = BrowserApp.selectedTab;
this._find = Cc["@mozilla.org/typeaheadfind;1"].createInstance(Ci.nsITypeAheadFind);
this._find.init(this._targetTab.browser.docShell);
this._initialViewport = JSON.stringify(this._targetTab.viewport);
this._viewportChanged = false;
}
let result = this._find.find(aSearchString, false);
this.handleResult(result);
},
findAgain: function(aString, aFindBackwards) {
let result = this._find.findAgain(aFindBackwards, false);
this.handleResult(result);
},
findClosed: function() {
if (!this._findInProgress) {
// this should never happen
Cu.reportError("Warning: findClosed() called while _findInProgress is false!");
// fall through and clean up anyway
}
this._find = null;
this._findInProgress = false;
this._targetTab = null;
this._initialViewport = null;
this._viewportChanged = false;
},
handleResult: function(aResult) {
if (aResult == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
if (this._viewportChanged) {
if (this._targetTab != BrowserApp.selectedTab) {
// this should never happen
Cu.reportError("Warning: selected tab changed during find!");
// fall through and restore viewport on the initial tab anyway
}
this._targetTab.viewport = JSON.parse(this._initialViewport);
this._targetTab.sendViewportUpdate();
}
} else {
this._viewportChanged = true;
}
}
};
var FormAssistant = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFormSubmitObserver]),