/** @file MyKeyboard.java
*
* @author marco corvi
* @date june 2012
*
* @brief TopoDroid numerical keyboard dialog
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.app.Dialog;
import android.widget.EditText;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.text.InputType;
import android.text.Editable;
import android.text.Layout;
import android.text.method.KeyListener;
import android.util.Log;
/* you need to override EditText::onTouchListener()
*/
public class MyKeyboard // FIXME DIALOG extends Dialog
implements OnKeyListener
, OnKeyboardActionListener
{
private static final String TAG = "DistoX0";
static final int FLAG_SIGN = 0x01;
static final int FLAG_POINT = 0x02;
static final int FLAG_DEGREE = 0x04;
static final int FLAG_LCASE = 0x08;
static final int FLAG_NOEDIT = 0x10;
static final int FLAG_2ND = 0x20;
static final int FLAG_POINT_SIGN = 0x03; // FLAG_POINT | FLAG_SIGN
static final int FLAG_POINT_DEGREE = 0x06; // FLAG_POINT | FLAG_DEGREE
static final int FLAG_POINT_SIGN_DEGREE = 0x07; // FLAG_POINT | FLAG_SIGN | FLAG_DEGREE
static final int FLAG_POINT_LCASE = 0x0a; // FLAG_POINT | FLAG_LCASE
static final int FLAG_POINT_LCASE_2ND = 0x2a; // FLAG_POINT | FLAG_LCASE | FLAG_2ND
boolean hasDegree;
boolean hasPoint;
boolean hasSign;
boolean hasLcase;
boolean inLcase;
Map< EditText, Integer > mFlags;
private Context mContext;
private EditText mEdit;
private KeyboardView mKeyboardView;
private Keyboard mKeyboard;
private Keyboard mKeyboard1;
private Keyboard mKeyboard2; // secondary kbd
EditText getEditText() { return mEdit; }
Context getContext() { return mContext; }
// Keyboard.Key mKeySign;
// Keyboard.Key mKeyDegree;
// Keyboard.Key mKeyMinute;
// Keyboard.Key mKeyPoint;
int setFlags( EditText e )
{
Integer j = mFlags.get( e );
int flag = ( j == null )? 0 : j.intValue();
hasSign = ( ( flag & FLAG_SIGN ) == FLAG_SIGN );
hasPoint = ( ( flag & FLAG_POINT ) == FLAG_POINT );
hasDegree = ( ( flag & FLAG_DEGREE ) == FLAG_DEGREE );
hasLcase = ( ( flag & FLAG_LCASE ) == FLAG_LCASE );
return flag;
}
Integer addFlag( EditText e, int f )
{
return mFlags.put( e, Integer.valueOf(f) );
}
static void registerEditText( final MyKeyboard kbd, final EditText e, int flag )
{
if ( kbd == null ) return;
if ( kbd.addFlag( e, flag ) == null ) {
// Log.v(TAG, "set listeners for " + e.getText().toString() );
if ( ( flag & FLAG_NOEDIT ) == FLAG_NOEDIT ) {
e.setBackgroundColor( 0xff999999 );
} else {
e.setBackgroundResource( android.R.drawable.edit_text );
}
e.setOnFocusChangeListener( new OnFocusChangeListener() {
@Override
public void onFocusChange( View v, boolean hasFocus ) {
CutNPaste.dismissPopup();
// Log.v(TAG, "onFocusChange() " + hasFocus + " " + e.getText().toString() );
if ( hasFocus ) {
InputMethodManager imm = (InputMethodManager)kbd.getContext().getSystemService( Context.INPUT_METHOD_SERVICE );
imm.hideSoftInputFromWindow( e.getWindowToken(), 0 );
if ( kbd.setEditText( e ) ) {
// e.setBackgroundResource( R.drawable.textfield_selected );
kbd.show( e );
// kbd.getWindow().makeActive();
} else {
// e.setBackgroundColor( 0xff999999 );
kbd.setEditText( null );
}
} else {
// e.setBackgroundResource( android.R.drawable.edit_text );
kbd.setEditText( null );
}
}
} );
e.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick( View v ) {
CutNPaste.dismissPopup();
// Log.v(TAG, "on click " + e.getText().toString() );
// EditText et = (EditText) v;
// EditText e0 = kbd.getEditText();
// if ( e0 != null ) {
// e0.setBackgroundResource( android.R.drawable.edit_text );
// }
e.setInputType( InputType.TYPE_NULL );
if ( kbd.setEditText( e ) ) {
// e.setBackgroundResource( android.R.drawable.edit_text );
// e.setBackgroundResource( R.drawable.textfield_selected );
kbd.show( e );
} else {
// e.setBackgroundColor( 0xff999999 );
kbd.setEditText( null );
}
}
} );
e.setInputType( InputType.TYPE_NULL );
e.setCursorVisible( true );
}
// if you need the cursor in the EditText use this
// e.setOnTouchListener( new OnTouchListener() {
// @Override
// public boolean onTouch( View v, MotionEvent ev ) {
// EditText et = (EditText)v;
// int t = et.getInputType();
// et.setInputType( InputType.TYPE_NULL );
// et.onTouchEvent( ev );
// et.setInputType( t );
// return true;
// }
// }
// FIXME getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
// FIXME
// @Override public void onBackPressed() {
// if ( kbd != null ) {
// kbd.hide();
// kbd.dismiss();
// kbd = null;
// }
// }
}
void hide()
{
mKeyboardView.setVisibility( View.GONE );
mKeyboardView.setEnabled( false );
}
private void show( View v )
{
mKeyboardView.setVisibility( View.VISIBLE );
mKeyboardView.setEnabled( true );
if ( v != null ) {
}
}
void switchKeyboard( int flag )
{
if ( mKeyboard2 == null ) return;
Keyboard next = ( (flag & FLAG_2ND) == FLAG_2ND )? mKeyboard2 : mKeyboard1;
if ( next == mKeyboard ) return;
boolean visible = mKeyboardView.isShown();
if ( visible ) hide();
mKeyboard = next;
mKeyboardView.setKeyboard(mKeyboard);
if ( ( flag & FLAG_LCASE ) == FLAG_LCASE ) {
setKeyLabels( false );
}
if ( visible ) show( null );
}
boolean isVisible()
{
return mKeyboardView.isShown();
}
public MyKeyboard( Context context, KeyboardView view, int kbdid1, int kbdid2 )
{
// FIXME DIALOG super( context );
mContext = context;
mEdit = null;
mFlags = new HashMap< EditText, Integer >();
// Log.v("DistoX", "id1 " + kbdid1 + " " + kbdid2 );
mKeyboardView = view;
mKeyboard1 = new Keyboard( mContext, kbdid1 );
mKeyboard2 = ( kbdid2 == -1 )? null : new Keyboard( mContext, kbdid2 );
mKeyboard = mKeyboard1;
mKeyboardView.setKeyboard(mKeyboard);
mKeyboardView.setEnabled(true);
mKeyboardView.setOnKeyListener(this);
mKeyboardView.setOnKeyboardActionListener(this);
mKeyboardView.setPreviewEnabled( false );
}
private boolean setEditText( EditText e )
{
if ( mEdit == e ) return true;
mEdit = e;
if ( mEdit != null ) {
int flag = setFlags( mEdit );
if ( ( flag & FLAG_NOEDIT ) == FLAG_NOEDIT ) {
mEdit = null;
return false;
}
switchKeyboard( flag );
return true;
} else {
hide();
}
return false;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
// Log.v( TAG, "[*] Keycode " + keyCode );
return false;
}
final static char CHAR_MINUS = (char)'-';
final static char CHAR_PLUS_MINUS = (char)177;
final static char CHAR_DEGREE = (char)176;
final static char CHAR_MINUTE = (char)39;
final static char CHAR_POINT = (char)46;
@Override
public void onKey(int keyCode, int[] keyCodes)
{
if ( keyCode == -4 /* Keyboard.KEYCODE_CANCEL */
|| keyCode == 4 /* hw KEYCODE_BACK */ ) {
// Log.v( TAG, "Keycode " + keyCode + " CANCEL");
hide();
return;
} else if ( keyCode == 256 ) {
hide();
if ( mEdit != null ) {
// cannot use FOCUS_FORWARD
View next = mEdit.focusSearch( View.FOCUS_RIGHT );
if ( next != null ) next.requestFocus();
}
} else if ( mEdit != null ) {
Editable editable = mEdit.getText() ;
int len = editable.length();
if ( keyCode == -5 /* Keyboard.KEYCODE_DELETE */ ) {
// Log.v( TAG, "Keycode " + keyCode + " DELETE len " + len + " text " + editable.toString());
if ( len > 0 ) {
editable.delete( len-1, len );
}
} else if ( keyCode == 177 ) { // +/-
if ( hasSign ) {
if ( len > 0 && editable.charAt(0) == CHAR_MINUS ) {
editable.delete(0,1);
} else {
editable.insert(0, "-" );
}
}
} else if ( keyCode == 257 ) { // Aa
if ( hasLcase ) {
setKeyLabels( ! inLcase );
}
} else if ( keyCode == 176 ) { // degree
if ( hasDegree && len > 0 ) {
boolean ok = true;
for ( int k=0; k<len; ++k) {
char ch = editable.charAt(k);
if ( ch == CHAR_MINUTE || ch == CHAR_POINT || ch == CHAR_DEGREE ) { ok = false; break; }
}
if ( ok ) editable.append( CHAR_DEGREE );
}
} else if ( keyCode == 39 ) { // minute
if ( hasDegree && len > 0 ) {
boolean ok = true;
for ( int k=0; k<len; ++k) {
char ch = editable.charAt(k);
if ( ch == CHAR_MINUTE || ch == CHAR_POINT ) { ok = false; break; }
}
if ( ok ) editable.append( CHAR_MINUTE );
}
} else if ( keyCode == 46 ) { // point
if ( hasPoint ) {
boolean ok = true;
for ( int k=0; k<len; ++k) {
char ch = editable.charAt(k);
if ( ch == CHAR_POINT ) { ok = false; break; }
}
if ( ok ) editable.append( CHAR_POINT );
}
} else {
// Log.v( TAG, "Keycode " + keyCode + " APPEND text " + editable.toString());
char ch = (char) keyCode;
if ( inLcase ) {
if ( ch >= 65 && ch <= 90 ) {
ch += 32;
}
}
editable.append( Character.toString(ch) );
}
// setTitle( editable.toString() );
} else {
// Log.d( TAG, "Keycode " + keyCode );
}
}
private void setKeyLabels( boolean lcase )
{
inLcase = lcase;
List< Keyboard.Key > keys = mKeyboard.getKeys();
for ( Keyboard.Key key : keys ) {
int c = key.codes[0];
int off = inLcase ? 32 : 0;
if ( c >= 65 && c <= 90 ) {
key.label = Character.toString( (char) (c+off) );
}
}
mKeyboardView.invalidateAllKeys();
}
// -----------------------------------------------------------
// KeyListener methods
// @Override
// public int getInputType()
// {
// return InputType.TYPE_NULL;
// }
// @Override
// public boolean onKeyDown( View view, Editable text, int keyCode, KeyEvent event)
// {
// Log.d(TAG, "onKeyDown keyCode=" + keyCode);
// return true; // key down handled
// }
// @Override
// public boolean onKeyOther(View view, Editable text, KeyEvent event)
// {
// Log.d(TAG, "onKeyOther keyCode=" + keyCode);
// return true; // key other handled
// }
// @Override
// public boolean onKeyUp(View view, Editable text, int keyCode, KeyEvent event)
// {
// Log.d(TAG, "onKeyUp keyCode=" + keyCode);
// return true; // key up handled
// }
// @Override
// public void clearMetaKeyState(View arg0, Editable arg1, int arg2) {
// }
// OnKeyboardActionListener methods
@Override
public void swipeUp()
{
// Log.d(TAG, "swipeUp");
}
@Override
public void swipeRight()
{
// Log.d(TAG, "swipeRight");
}
@Override
public void swipeLeft()
{
// Log.d(TAG, "swipeLeft");
}
@Override
public void swipeDown()
{
// Log.d(TAG, "swipeDown");
}
@Override
public void onText(CharSequence text)
{
// Log.d(TAG, "onText? \"" + text + "\"");
}
@Override
public void onRelease(int primaryCode)
{
// Log.d(TAG, "onRelease? primaryCode=" + primaryCode);
}
@Override
public void onPress(int primaryCode)
{
// Log.d(TAG, "onPress? primaryCode=" + primaryCode);
}
}