Bug 1050480 - Add a match case option to find-in-page, r=wesj
authorMark Capella <markcapella@twcny.rr.com>
Tue, 11 Nov 2014 01:11:46 -0500
changeset 214910 48f77459558026e1d16aad579a4c9a51268b3e69
parent 214909 75c7f78a6b42559cac7b626497a9d1230c7019a4
child 214911 4b4b6b20ae2dd81b5d79006d78f2a210a2a8e6f0
child 214943 adbbce7da1b1447c6336c48ea42a0430cf8fe081
push id9879
push usermarkcapella@twcny.rr.com
push dateTue, 11 Nov 2014 06:11:53 +0000
treeherderfx-team@48f774595580 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswesj
bugs1050480
milestone36.0a1
Bug 1050480 - Add a match case option to find-in-page, r=wesj
mobile/android/base/FindInPageBar.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/drawable/find_matchcase_selector.xml
mobile/android/base/resources/layout/find_in_page_content.xml
mobile/android/base/resources/values/colors.xml
mobile/android/base/resources/values/dimens.xml
mobile/android/chrome/content/FindHelper.js
mobile/android/services/strings.xml.in
--- a/mobile/android/base/FindInPageBar.java
+++ b/mobile/android/base/FindInPageBar.java
@@ -4,37 +4,40 @@
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.GeckoRequest;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.ThreadUtils;
 
+import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.content.Context;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.CheckedTextView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnClickListener, GeckoEventListener  {
-    private static final String LOGTAG = "FindInPageBar";
+    private static final String LOGTAG = "GeckoFindInPageBar";
     private static final String REQUEST_ID = "FindInPageBar";
 
     private final Context mContext;
     private CustomEditText mFindText;
+    private CheckedTextView mMatchCase;
     private TextView mStatusText;
     private boolean mInflated;
 
     public FindInPageBar(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
         setFocusable(true);
     }
@@ -59,16 +62,19 @@ public class FindInPageBar extends Linea
                 if (keyCode == KeyEvent.KEYCODE_BACK) {
                     hide();
                     return true;
                 }
                 return false;
             }
         });
 
+        mMatchCase = (CheckedTextView) content.findViewById(R.id.find_matchcase);
+        mMatchCase.setOnClickListener(this);
+
         mStatusText = (TextView) content.findViewById(R.id.find_status);
 
         mInflated = true;
         EventDispatcher.getInstance().registerGeckoThreadListener(this, "TextSelection:Data");
     }
 
     public void show() {
         if (!mInflated)
@@ -118,16 +124,26 @@ public class FindInPageBar extends Linea
     }
 
     // View.OnClickListener implementation
 
     @Override
     public void onClick(View v) {
         final int viewId = v.getId();
 
+        if (viewId == R.id.find_matchcase) {
+            // Toggle matchcase state (color).
+            mMatchCase.toggle();
+
+            // Repeat the find after a matchcase change.
+            sendRequestToFinderHelper("FindInPage:Find", mFindText.getText().toString());
+            getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
+            return;
+        }
+
         if (viewId == R.id.find_prev) {
             sendRequestToFinderHelper("FindInPage:Prev", mFindText.getText().toString());
             getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
             return;
         }
 
         if (viewId == R.id.find_next) {
             sendRequestToFinderHelper("FindInPage:Next", mFindText.getText().toString());
@@ -179,17 +195,26 @@ public class FindInPageBar extends Linea
             });
         }
     }
 
     /**
      * Request find operation, and update matchCount results (current count and total).
      */
     private void sendRequestToFinderHelper(final String request, final String searchString) {
-        GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, searchString) {
+        final JSONObject json = new JSONObject();
+        try {
+            json.put("searchString", searchString);
+            json.put("matchCase", mMatchCase.isChecked());
+        } catch (JSONException e) {
+            Log.e(LOGTAG, "JSON error - Error creating JSONObject", e);
+            return;
+        }
+
+        GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, json) {
             @Override
             public void onResponse(NativeJSObject nativeJSObject) {
                 final int total = nativeJSObject.optInt("total", 0);
                 final int current = nativeJSObject.optInt("current", 0);
                 updateResult(total, current);
             }
 
             public void onError() {
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -552,8 +552,13 @@ just addresses the organization to follo
 
 <!-- Localization note (remote_tabs_last_synced): the variable is replaced by a
      "relative time span string" produced by Android.  This string describes the
      time the tabs were last synced relative to the current time; examples
      include "42 minutes ago", "4 days ago", "last week", etc. The subject of
      "Last synced" is one of the user's other Sync clients, typically Firefox on
      their desktop or laptop.-->
 <!ENTITY remote_tabs_last_synced "Last synced: &formatS;">
+
+<!-- Find-In-Page strings -->
+<!-- LOCALIZATION NOTE (find_matchcase): This is meant to appear as an icon that changes color
+     if match-case is activated. i.e. No more than two letters, one uppercase, one lowercase. -->
+<!ENTITY find_matchcase "Aa">
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/find_matchcase_selector.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_checked="true"
+          android:color="@color/find_matchcase_on"/>
+
+    <item android:state_checked="false"
+          android:color="@color/find_matchcase_off"/>
+
+</selector>
--- a/mobile/android/base/resources/layout/find_in_page_content.xml
+++ b/mobile/android/base/resources/layout/find_in_page_content.xml
@@ -23,16 +23,25 @@
 
     <TextView android:id="@+id/find_status"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_marginRight="@dimen/find_in_page_status_margin_right"
               android:textColor="@color/find_status_default"
               android:visibility="gone"/>
 
+    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+                     android:id="@+id/find_matchcase"
+                     android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:layout_marginRight="@dimen/find_in_page_matchcase_margin_right"
+                     android:checked="false"
+                     android:text="@string/find_matchcase"
+                     android:textColor="@drawable/find_matchcase_selector"/>
+
     <ImageButton android:id="@+id/find_prev"
                  style="@style/FindBar.ImageButton"
                  android:contentDescription="@string/find_prev"
                  android:layout_marginTop="@dimen/find_in_page_control_margin_top"
                  android:src="@drawable/find_prev"/>
 
     <ImageButton android:id="@+id/find_next"
                  style="@style/FindBar.ImageButton"
--- a/mobile/android/base/resources/values/colors.xml
+++ b/mobile/android/base/resources/values/colors.xml
@@ -147,16 +147,18 @@
   <color name="tab_history_timeline_separator">#D7D9DB</color>
   <color name="tab_history_favicon_border">#D7D9DB</color>
   <color name="tab_history_favicon_background">#FFFFFF</color>
   <color name="tab_history_title_color">#363B40</color>
   <color name="tab_history_border_color">#DADADF</color>
 
   <!-- Colour used for Find-In-Page dialog -->
   <color name="find_status_default">#AFB1B3</color>
+  <color name="find_matchcase_on">#AFB1B3</color>
+  <color name="find_matchcase_off">#D02626</color>
 
   <!-- Canvas delegate paint color -->
   <color name="canvas_delegate_paint">#FFFF0000</color>
 
   <!-- Top sites thumbnail colors -->
   <color name="top_site_default">#FFECF0F3</color>
   <color name="top_site_border">#FFCFD9E1</color>
 
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -178,12 +178,13 @@
     <dimen name="tab_history_bg_width">2dp</dimen>
     <dimen name="tab_history_border_padding">2dp</dimen>
 
     <!-- Find-In-Page dialog dimensions. -->
     <dimen name="find_in_page_text_margin_left">5dip</dimen>
     <dimen name="find_in_page_text_margin_right">12dip</dimen>
     <dimen name="find_in_page_text_padding_left">10dip</dimen>
     <dimen name="find_in_page_text_padding_right">10dip</dimen>
-    <dimen name="find_in_page_status_margin_right">5dip</dimen>
+    <dimen name="find_in_page_status_margin_right">15dip</dimen>
+    <dimen name="find_in_page_matchcase_margin_right">10dip</dimen>
     <dimen name="find_in_page_control_margin_top">2dip</dimen>
 
 </resources>
--- a/mobile/android/chrome/content/FindHelper.js
+++ b/mobile/android/chrome/content/FindHelper.js
@@ -28,28 +28,28 @@ var FindHelper = {
         this._uninit();
         this._findClosed();
         break;
     }
   },
 
   _findOpened: function() {
     Messaging.addListener((data) => {
-      this.doFind(data);
-      return this._getMatchesCountResult(data);
+      this.doFind(data.searchString, data.matchCase);
+      return this._getMatchesCountResult(data.searchString);
     }, "FindInPage:Find");
 
     Messaging.addListener((data) => {
-      this.findAgain(data, false);
-      return this._getMatchesCountResult(data);
+      this.findAgain(data.searchString, false, data.matchCase);
+      return this._getMatchesCountResult(data.searchString);
     }, "FindInPage:Next");
 
     Messaging.addListener((data) => {
-      this.findAgain(data, true);
-      return this._getMatchesCountResult(data);
+      this.findAgain(data.searchString, true, data.matchCase);
+      return this._getMatchesCountResult(data.searchString);
     }, "FindInPage:Prev");
   },
 
   _init: function() {
     // If there's no find in progress, start one.
     if (this._finder) {
       return;
     }
@@ -94,32 +94,34 @@ var FindHelper = {
 
   /**
    * Pass along the count results to FindInPageBar for display.
    */
   onMatchesCountResult: function(result) {
     this._matchesCountResult = result;
   },
 
-  doFind: function(aSearchString) {
+  doFind: function(searchString, matchCase) {
     if (!this._finder) {
       this._init();
     }
 
-    this._finder.fastFind(aSearchString, false);
+    this._finder.caseSensitive = matchCase;
+    this._finder.fastFind(searchString, false);
   },
 
-  findAgain: function(aString, aFindBackwards) {
+  findAgain: function(searchString, findBackwards, matchCase) {
     // This can happen if the user taps next/previous after re-opening the search bar
     if (!this._finder) {
-      this.doFind(aString);
+      this.doFind(searchString, matchCase);
       return;
     }
 
-    this._finder.findAgain(aFindBackwards, false, false);
+    this._finder.caseSensitive = matchCase;
+    this._finder.findAgain(findBackwards, false, false);
   },
 
   onFindResult: function(aData) {
     if (aData.result == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
       if (this._viewportChanged) {
         if (this._targetTab != BrowserApp.selectedTab) {
           // this should never happen
           Cu.reportError("Warning: selected tab changed during find!");
--- a/mobile/android/services/strings.xml.in
+++ b/mobile/android/services/strings.xml.in
@@ -211,8 +211,11 @@
 <string name="fxaccount_sync_sign_in_error_notification_title">&fxaccount_sync_sign_in_error_notification_title2;</string>
 <string name="fxaccount_sync_sign_in_error_notification_text">&fxaccount_sync_sign_in_error_notification_text2;</string>
 
 <!-- Remove Account -->
 <string name="fxaccount_remove_account_dialog_title">&fxaccount_remove_account_dialog_title;</string>
 <string name="fxaccount_remove_account_dialog_message">&fxaccount_remove_account_dialog_message;</string>
 <string name="fxaccount_remove_account_toast">&fxaccount_remove_account_toast;</string>
 <string name="fxaccount_remove_account_menu_item">&fxaccount_remove_account_menu_item;</string>
+
+<!-- Find-In-Page strings -->
+<string name="find_matchcase">&find_matchcase;</string>