summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid A. Madore <david+git@madore.org>2010-04-27 02:13:49 +0200
committerDavid A. Madore <david+git@madore.org>2010-04-27 02:24:17 +0200
commit221e994358da9d5e18fe490a19389093dfe4e755 (patch)
treea386603af4a5cf4ee501c4456d653560b8965058
parente37377a5d3ca4c78c440b097af4186cbbd81a6a0 (diff)
downloadUnicodeMap-221e994358da9d5e18fe490a19389093dfe4e755.tar.gz
UnicodeMap-221e994358da9d5e18fe490a19389093dfe4e755.tar.bz2
UnicodeMap-221e994358da9d5e18fe490a19389093dfe4e755.zip
Implement a search mechanism.
-rw-r--r--res/layout/main_layout.xml2
-rw-r--r--res/layout/search_dialog.xml24
-rw-r--r--res/menu/options_menu.xml5
-rw-r--r--res/values/strings.xml5
-rw-r--r--src/org/madore/android/unicodeMap/UnicodeDatabase.java12
-rw-r--r--src/org/madore/android/unicodeMap/UnicodeMapActivity.java109
6 files changed, 151 insertions, 6 deletions
diff --git a/res/layout/main_layout.xml b/res/layout/main_layout.xml
index 571a2dc..89480d7 100644
--- a/res/layout/main_layout.xml
+++ b/res/layout/main_layout.xml
@@ -21,7 +21,7 @@
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1" />
- <Button android:id="@+id/button"
+ <Button android:id="@+id/copyButton"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="@string/copy_button" />
diff --git a/res/layout/search_dialog.xml b/res/layout/search_dialog.xml
new file mode 100644
index 0000000..7c7be92
--- /dev/null
+++ b/res/layout/search_dialog.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:orientation="vertical">
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <EditText android:id="@+id/searchTerm"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ <Button android:id="@+id/searchButton"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:text="@string/search_button" />
+ </LinearLayout>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/search_hint" />
+</LinearLayout>
diff --git a/res/menu/options_menu.xml b/res/menu/options_menu.xml
new file mode 100644
index 0000000..a187813
--- /dev/null
+++ b/res/menu/options_menu.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menuSearch"
+ android:title="@string/menu_search" />
+</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 605a255..b77be4a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6,4 +6,9 @@
<string name="copy_button">Copy</string>
<string name="copied_toast">Copied to clipboard</string>
<string name="empty_list">(Empty!)</string>
+ <string name="menu_search">Search</string>
+ <string name="search_title">Search in character names</string>
+ <string name="search_button">Search</string>
+ <string name="search_hint">Case is insensitive and matches whole string; use a % sign as wildcard (e.g.: "latin%letter r%")</string>
+ <string name="list_too_long">Only %d first results shown</string>
</resources>
diff --git a/src/org/madore/android/unicodeMap/UnicodeDatabase.java b/src/org/madore/android/unicodeMap/UnicodeDatabase.java
index b81c99a..84efb63 100644
--- a/src/org/madore/android/unicodeMap/UnicodeDatabase.java
+++ b/src/org/madore/android/unicodeMap/UnicodeDatabase.java
@@ -217,7 +217,17 @@ public class UnicodeDatabase {
"id >= ? AND id < ?",
new String[] { Integer.toString(from),
Integer.toString(to) },
- null, null, null, null);
+ null, null, "id", null);
+ return new CursorIterable(c);
+ }
+
+ public Iterable<UnicodeCharacter> searchNames(String like, int limit) {
+ final Cursor c
+ = db.query(UNICODE_TABLE_NAME, queryColumns,
+ "name LIKE ?",
+ new String[] { like },
+ null, null, "id",
+ (limit>0)?Integer.toString(limit):null);
return new CursorIterable(c);
}
diff --git a/src/org/madore/android/unicodeMap/UnicodeMapActivity.java b/src/org/madore/android/unicodeMap/UnicodeMapActivity.java
index 1b43d9d..74dca91 100644
--- a/src/org/madore/android/unicodeMap/UnicodeMapActivity.java
+++ b/src/org/madore/android/unicodeMap/UnicodeMapActivity.java
@@ -4,13 +4,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Formatter;
+import java.util.regex.Pattern;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuInflater;
import android.view.KeyEvent;
import android.widget.*;
import android.text.ClipboardManager;
@@ -83,7 +88,10 @@ public final class UnicodeMapActivity extends ListActivity {
list);
stack.add(adapter);
positionStack.add(position);
- positionYStack.add(view.getTop());
+ if ( view != null )
+ positionYStack.add(view.getTop());
+ else
+ positionYStack.add(0);
setListAdapter(adapter);
} else
throw new AssertionError("unknown UnicodeDisplayable");
@@ -159,12 +167,12 @@ public final class UnicodeMapActivity extends ListActivity {
setListAdapter(rootAdapter);
final ClipboardManager cmgr
= (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
- final Button btn = (Button) findViewById(R.id.button);
+ final Button btn = (Button) findViewById(R.id.copyButton);
textForm = (EditText) findViewById(R.id.edit);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
cmgr.setText(textForm.getText());
- Toast.makeText(getApplicationContext(),
+ Toast.makeText(UnicodeMapActivity.this,
R.string.copied_toast,
Toast.LENGTH_SHORT).show();
}
@@ -176,17 +184,110 @@ public final class UnicodeMapActivity extends ListActivity {
lv.setOnItemLongClickListener(listener);
}
+ final static int searchLimit = 1000;
+
+ protected void doSearch(String s) {
+ List<UnicodeDisplayable> list
+ = new ArrayList<UnicodeDisplayable>(128);
+ for ( UnicodeCharacter ch : db.searchNames(s,searchLimit+1) )
+ list.add(ch);
+ boolean overflowed = ( list.size() > searchLimit );
+ if ( overflowed )
+ list.remove(list.size()-1);
+ UnicodeArrayAdapter adapter
+ = new UnicodeArrayAdapter(UnicodeMapActivity.this,
+ list);
+ stack.add(adapter);
+ final ListView lv = getListView();
+ int position = lv.getSelectedItemPosition();
+ int position0 = lv.getFirstVisiblePosition();
+ if ( position == AdapterView.INVALID_POSITION )
+ position = position0;
+ positionStack.add(position);
+ View view = lv.getChildAt(position-position0);
+ if ( view != null )
+ positionYStack.add(view.getTop());
+ else
+ positionYStack.add(0);
+ setListAdapter(adapter);
+ if ( overflowed ) {
+ String str = getResources().getString(R.string.list_too_long);
+ android.util.Log.e("UnicodeMapActivity", "format is: "+str);
+ Toast.makeText(UnicodeMapActivity.this,
+ String.format(str, searchLimit),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ protected void querySearch() {
+ final Dialog dialog = new Dialog(UnicodeMapActivity.this);
+ // dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setTitle(R.string.search_title);
+ dialog.setOwnerActivity(this);
+ dialog.setContentView(R.layout.search_dialog);
+ dialog.setCancelable(true);
+ dialog.getWindow().setLayout(ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ final EditText textForm
+ = (EditText) dialog.findViewById(R.id.searchTerm);
+ textForm.setOnKeyListener(new View.OnKeyListener() {
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ if ( ( event.getAction() == KeyEvent.ACTION_DOWN )
+ && ( keyCode == KeyEvent.KEYCODE_ENTER ) ) {
+ String s = textForm.getText().toString();
+ if ( ! Pattern.matches("^\\s*$", s) )
+ doSearch(s);
+ dialog.dismiss();
+ return true;
+ }
+ return false;
+ }
+ });
+ final Button btn = (Button) dialog.findViewById(R.id.searchButton);
+ btn.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View view) {
+ String s = textForm.getText().toString();
+ if ( ! Pattern.matches("^\\s*$", s) ) {
+ doSearch(s);
+ dialog.dismiss();
+ }
+ }
+ });
+ dialog.show();
+ }
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if ( ( keyCode == KeyEvent.KEYCODE_BACK) && stack.size() > 1 ) {
+ if ( ( keyCode == KeyEvent.KEYCODE_BACK ) && stack.size() > 1 ) {
final ListView lv = getListView();
stack.remove(stack.size()-1);
setListAdapter(stack.get(stack.size()-1));
lv.setSelectionFromTop(positionStack.remove(positionStack.size()-1),
positionYStack.remove(positionYStack.size()-1));
return true;
+ } else if ( keyCode == KeyEvent.KEYCODE_SEARCH ) {
+ querySearch();
+ return true;
}
return super.onKeyDown(keyCode, event);
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch ( item.getItemId() ) {
+ case R.id.menuSearch:
+ querySearch();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.options_menu, menu);
+ return true;
+ }
+
}