package org.madore.android.unicodeMap; 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; import android.app.ListActivity; import android.app.Dialog; import android.app.ProgressDialog; public final class UnicodeMapActivity extends ListActivity { protected UnicodeDatabase db; protected class ViewHistory { public final UnicodeArrayAdapter adapter; public final int selPosition; public final int yOffset; public final CharSequence title; public ViewHistory(UnicodeArrayAdapter adapter, int selPosition, int yOffset, CharSequence title) { this.adapter = adapter; this.selPosition = selPosition; this.yOffset = yOffset; this.title = title; } } protected final List historyStack = new ArrayList(10); EditText textForm; protected void launchPopulation() { final ProgressDialog progress = new ProgressDialog(this); progress.setOwnerActivity(this); progress.setTitle(R.string.loading_database_title); progress.setMessage(getResources().getText(R.string.loading_database_msg)); progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progress.setCancelable(false); progress.show(); final Handler handler = new Handler() { public void handleMessage(Message msg) { int done = msg.getData().getInt("done"); int total = msg.getData().getInt("total"); progress.setMax(total); progress.setProgress(done); if ( done >= total ) progress.dismiss(); } }; final Thread thr = new Thread() { public void run() { final UnicodeDatabase writeDb = new UnicodeDatabase(UnicodeMapActivity.this); writeDb.populate(handler); } }; thr.start(); } protected void saveView(View selView, int selPosition) { final ListView lv = getListView(); lv.clearTextFilter(); final UnicodeArrayAdapter adapter = (UnicodeArrayAdapter) lv.getAdapter(); final int yOffset; if ( selView != null ) yOffset = selView.getTop(); else yOffset = 0; CharSequence title = getTitle(); historyStack.add(new ViewHistory(adapter, selPosition, yOffset, title)); } protected void saveView() { final ListView lv = getListView(); lv.clearTextFilter(); final UnicodeArrayAdapter adapter = (UnicodeArrayAdapter) lv.getAdapter(); int position = lv.getSelectedItemPosition(); int position0 = lv.getFirstVisiblePosition(); if ( position == AdapterView.INVALID_POSITION ) position = position0; View view = lv.getChildAt(position-position0); final int yOffset; if ( view != null ) yOffset = view.getTop(); else yOffset = 0; CharSequence title = getTitle(); historyStack.add(new ViewHistory(adapter, position, yOffset, title)); } protected class MapItemClickListener implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener { public void onItemClick(AdapterView parent, View view, int position, long id) { UnicodeDisplayable it = (UnicodeDisplayable)parent.getItemAtPosition(position); if ( it instanceof UnicodeCharacter ) textForm.append(((UnicodeCharacter)it).getChar()); else if ( it instanceof UnicodeCharacter.Range ) { int from = ((UnicodeCharacter.Range)it).getFrom(); int to = ((UnicodeCharacter.Range)it).getTo(); List list = new ArrayList(db.countRange(from,to)); for ( UnicodeCharacter ch : db.getRange(from,to) ) list.add(ch); UnicodeArrayAdapter adapter = new UnicodeArrayAdapter(UnicodeMapActivity.this, list); saveView(view, position); setListAdapter(adapter); setTitle(String.format(getResources() .getString(R.string.app_name_spec), ((UnicodeCharacter.Range)it).getDescr())); } else throw new AssertionError("unknown UnicodeDisplayable"); } public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { UnicodeDisplayable it = (UnicodeDisplayable)parent.getItemAtPosition(position); if ( it instanceof UnicodeCharacter ) { UnicodeCharacter itch = (UnicodeCharacter)it; Dialog dialog = new Dialog(UnicodeMapActivity.this); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setOwnerActivity(UnicodeMapActivity.this); dialog.setContentView(R.layout.char_details); dialog.setCancelable(true); TextView text; text = (TextView) dialog.findViewById(R.id.detailsLabel); text.setText(itch.getLabel()); text = (TextView) dialog.findViewById(R.id.encodingLabel); StringBuilder s = new StringBuilder(); Formatter fmt = new Formatter(s); fmt.format("UTF-8:"); byte[] bytes; bytes = UnicodeCharacter.toUtf8(itch.getChar()); for ( int i=0 ; i rootList = new ArrayList(UnicodeCharacter.Range.values().length); for ( UnicodeCharacter.Range rng : UnicodeCharacter.Range.values() ) rootList.add(rng); UnicodeArrayAdapter rootAdapter = new UnicodeArrayAdapter(this, rootList); setListAdapter(rootAdapter); final ClipboardManager cmgr = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); 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(UnicodeMapActivity.this, R.string.copied_toast, Toast.LENGTH_SHORT).show(); } }); final ListView lv = getListView(); lv.setTextFilterEnabled(true); MapItemClickListener listener = new MapItemClickListener(); lv.setOnItemClickListener(listener); lv.setOnItemLongClickListener(listener); } final static int searchLimit = 1000; protected void doSearch(String s) { List list = new ArrayList(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); saveView(); setListAdapter(adapter); setTitle(String.format(getResources() .getString(R.string.app_name_spec), getResources() .getString(R.string.search_results))); 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 ) && historyStack.size() > 0 ) { final ListView lv = getListView(); ViewHistory saved = historyStack.remove(historyStack.size()-1); setListAdapter(saved.adapter); setTitle(saved.title); lv.setSelectionFromTop(saved.selPosition, saved.yOffset); 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; } }