/** * Copyright (C) 2009 Michael A. MacDonald */ package android.androidVNC; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Map.Entry; import com.cgcl.cloudesk.cloudeskmain.screens.act.R; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.AdapterView; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; /** * @author Michael A. MacDonald * */ class MetaKeyDialog extends Dialog implements ConnectionSettable { CheckBox _checkShift; CheckBox _checkCtrl; CheckBox _checkAlt; TextView _textKeyDesc; EditText _textListName; Spinner _spinnerKeySelect; Spinner _spinnerKeysInList; Spinner _spinnerLists; VncDatabase _database; static ArrayList<MetaList> _lists; ArrayList<MetaKeyBean> _keysInList; long _listId; VncCanvasActivity _canvasActivity; MetaKeyBean _currentKeyBean; static final String[] EMPTY_ARGS = new String[0]; ConnectionBean _connection; /** * @param context */ public MetaKeyDialog(Context context) { super(context); setOwnerActivity((Activity)context); _canvasActivity = (VncCanvasActivity)context; } /* (non-Javadoc) * @see android.app.Dialog#onCreateOptionsMenu(android.view.Menu) */ @Override public boolean onCreateOptionsMenu(Menu menu) { _canvasActivity.getMenuInflater().inflate(R.menu.metakeymenu, menu); menu.findItem(R.id.itemDeleteKeyList).setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() { /* (non-Javadoc) * @see android.view.MenuItem.OnMenuItemClickListener#onMenuItemClick(android.view.MenuItem) */ @Override public boolean onMenuItemClick(MenuItem item) { Utils.showYesNoPrompt(_canvasActivity, "Delete key list", "Delete list "+_textListName.getText().toString(), new OnClickListener() { /* (non-Javadoc) * @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int) */ @Override public void onClick(DialogInterface dialog, int which) { int position = _spinnerLists.getSelectedItemPosition(); if (position == Spinner.INVALID_POSITION) return; _listId = _lists.get(position).get_Id(); if (_listId > 1) { _lists.remove(position); ArrayAdapter<String> adapter = getSpinnerAdapter(_spinnerLists); adapter.remove(adapter.getItem(position)); SQLiteDatabase db = _database.getWritableDatabase(); db.execSQL(MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}", MetaKeyBean.GEN_TABLE_NAME, MetaKeyBean.GEN_FIELD_METALISTID, _listId)); db.execSQL(MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}", MetaList.GEN_TABLE_NAME, MetaList.GEN_FIELD__ID, _listId)); _connection.setMetaListId(1); _connection.save(db); setMetaKeyList(); } } }, null); return true; } }); menu.findItem(R.id.itemDeleteKey).setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() { /* (non-Javadoc) * @see android.view.MenuItem.OnMenuItemClickListener#onMenuItemClick(android.view.MenuItem) */ @Override public boolean onMenuItemClick(MenuItem item) { final int position = _spinnerKeysInList.getSelectedItemPosition(); if (position != Spinner.INVALID_POSITION) { final MetaKeyBean toDelete = _keysInList.get(position); Utils.showYesNoPrompt(_canvasActivity, "Delete from list", "Delete key " + toDelete.getKeyDesc(), new OnClickListener() { /* (non-Javadoc) * @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int) */ @Override public void onClick(DialogInterface dialog, int which) { getSpinnerAdapter(_spinnerKeysInList).remove(toDelete.getKeyDesc()); _keysInList.remove(position); SQLiteDatabase db = _database.getWritableDatabase(); db.execSQL( MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}", MetaKeyBean.GEN_TABLE_NAME, MetaKeyBean.GEN_FIELD_METALISTID, toDelete.get_Id()) ); if (_connection.getLastMetaKeyId() == toDelete.get_Id()) { _connection.setLastMetaKeyId(0); _connection.save(db); } int newPos = _spinnerKeysInList.getSelectedItemPosition(); if (newPos != Spinner.INVALID_POSITION && newPos < _keysInList.size()) { _currentKeyBean = new MetaKeyBean(_keysInList.get(newPos)); updateDialogForCurrentKey(); } } }, null); } return true; } }); return true; } /* (non-Javadoc) * @see android.app.Dialog#onMenuOpened(int, android.view.Menu) */ @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.itemDeleteKeyList).setEnabled(_currentKeyBean.getMetaListId()>1); menu.findItem(R.id.itemDeleteKey).setEnabled(_spinnerKeysInList.getSelectedItemPosition()!=Spinner.INVALID_POSITION); return true; } /* (non-Javadoc) * @see android.app.Dialog#onCreate(android.os.Bundle) */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.metakey); setTitle(R.string.meta_key_title); _checkShift = (CheckBox)findViewById(R.id.checkboxShift); _checkCtrl = (CheckBox)findViewById(R.id.checkboxCtrl); _checkAlt = (CheckBox)findViewById(R.id.checkboxAlt); _textKeyDesc = (TextView)findViewById(R.id.textKeyDesc); _textListName = (EditText)findViewById(R.id.textListName); _spinnerKeySelect = (Spinner)findViewById(R.id.spinnerKeySelect); _spinnerKeysInList = (Spinner)findViewById(R.id.spinnerKeysInList); _spinnerLists = (Spinner)findViewById(R.id.spinnerLists); _database = _canvasActivity.database; if (_lists == null) { _lists = new ArrayList<MetaList>(); MetaList.getAll(_database.getReadableDatabase(), MetaList.GEN_TABLE_NAME, _lists, MetaList.GEN_NEW); } _spinnerKeySelect.setAdapter(new ArrayAdapter<String>(getOwnerActivity(), android.R.layout.simple_spinner_item, MetaKeyBean.allKeysNames)); _spinnerKeySelect.setSelection(0); setListSpinner(); _checkShift.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.SHIFT_MASK)); _checkAlt.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.ALT_MASK)); _checkCtrl.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.CTRL_MASK)); _spinnerLists.setOnItemSelectedListener(new OnItemSelectedListener() { /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long) */ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { _connection.setMetaListId(_lists.get(position).get_Id()); _connection.Gen_update(_database.getWritableDatabase()); setMetaKeyList(); } /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView) */ public void onNothingSelected(AdapterView<?> parent) { } }); _spinnerKeysInList.setOnItemSelectedListener(new OnItemSelectedListener() { /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long) */ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { _currentKeyBean = new MetaKeyBean(_keysInList.get(position)); updateDialogForCurrentKey(); } /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView) */ public void onNothingSelected(AdapterView<?> parent) { } }); _spinnerKeySelect.setOnItemSelectedListener(new OnItemSelectedListener() { /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long) */ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (_currentKeyBean == null) { _currentKeyBean = new MetaKeyBean(0,0,MetaKeyBean.allKeys.get(position)); } else { _currentKeyBean.setKeyBase(MetaKeyBean.allKeys.get(position)); } updateDialogForCurrentKey(); } /* (non-Javadoc) * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView) */ public void onNothingSelected(AdapterView<?> parent) { } }); ((Button)findViewById(R.id.buttonSend)).setOnClickListener(new View.OnClickListener() { /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ public void onClick(View v) { sendCurrentKey(); dismiss(); } }); ((Button)findViewById(R.id.buttonNewList)).setOnClickListener(new View.OnClickListener() { /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { MetaList newList = new MetaList(); newList.setName("New"); SQLiteDatabase db = _database.getWritableDatabase(); newList.Gen_insert(db); _connection.setMetaListId(newList.get_Id()); _connection.save(db); _lists.add(newList); getSpinnerAdapter(_spinnerLists).add(newList.getName()); setMetaKeyList(); } }); ((Button)findViewById(R.id.buttonCopyList)).setOnClickListener(new View.OnClickListener() { /* (non-Javadoc) * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { MetaList newList = new MetaList(); newList.setName("Copy of " + _textListName.getText().toString()); SQLiteDatabase db = _database.getWritableDatabase(); newList.Gen_insert(db); db.execSQL(MessageFormat.format(getCopyListString(), newList.get_Id(), _listId)); _connection.setMetaListId(newList.get_Id()); _connection.save(db); _lists.add(newList); getSpinnerAdapter(_spinnerLists).add(newList.getName()); setMetaKeyList(); } }); } private static String copyListString; private String getCopyListString() { if (copyListString==null) { StringBuilder sb = new StringBuilder("INSERT INTO "); sb.append(MetaKeyBean.GEN_TABLE_NAME); sb.append(" ( "); sb.append(MetaKeyBean.GEN_FIELD_METALISTID); StringBuilder fieldList = new StringBuilder(); for (Entry<String,Object> s : _currentKeyBean.Gen_getValues().valueSet()) { if (!s.getKey().equals(MetaKeyBean.GEN_FIELD__ID) && !s.getKey().equals(MetaKeyBean.GEN_FIELD_METALISTID)) { fieldList.append(','); fieldList.append(s.getKey()); } } String fl = fieldList.toString(); sb.append(fl); sb.append(" ) SELECT {0} "); sb.append(fl); sb.append(" FROM "); sb.append(MetaKeyBean.GEN_TABLE_NAME); sb.append(" WHERE "); sb.append(MetaKeyBean.GEN_FIELD_METALISTID); sb.append(" = {1}"); copyListString = sb.toString(); } return copyListString; } private boolean _justStarted; /* (non-Javadoc) * @see android.app.Dialog#onStart() */ @Override protected void onStart() { takeKeyEvents(true); _justStarted = true; super.onStart(); View v = getCurrentFocus(); if (v!=null) v.clearFocus(); } /* (non-Javadoc) * @see android.app.Dialog#onStop() */ @Override protected void onStop() { int i = 0; for (MetaList l : _lists) { if (l.get_Id() == _listId) { String s = _textListName.getText().toString(); if (! s.equals(l.getName())) { l.setName(s); l.Gen_update(_database.getWritableDatabase()); ArrayAdapter<String> adapter = getSpinnerAdapter(_spinnerLists); adapter.remove(adapter.getItem(i)); adapter.insert(s,i); } break; } i++; } takeKeyEvents(false); super.onStop(); } /* (non-Javadoc) * @see android.app.Dialog#onKeyDown(int, android.view.KeyEvent) */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { _justStarted = false; if (keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_MENU && getCurrentFocus() == null) { int flags = event.getMetaState(); int currentFlags = _currentKeyBean.getMetaFlags(); MetaKeyBase base = MetaKeyBean.keysByKeyCode.get(keyCode); if (base != null) { if (0 != (flags & KeyEvent.META_SHIFT_ON)) { currentFlags |= VncCanvas.SHIFT_MASK; } if (0 != (flags & KeyEvent.META_ALT_ON)) { currentFlags |= VncCanvas.ALT_MASK; } _currentKeyBean.setKeyBase(base); } else { // Toggle flags according to meta keys if (0 != (flags & KeyEvent.META_SHIFT_ON)) { currentFlags ^= VncCanvas.SHIFT_MASK; } if (0 != (flags & KeyEvent.META_ALT_ON)) { currentFlags ^= VncCanvas.ALT_MASK; } if (keyCode == KeyEvent.KEYCODE_SEARCH) { currentFlags ^= VncCanvas.CTRL_MASK; } } _currentKeyBean.setMetaFlags(currentFlags); updateDialogForCurrentKey(); return true; } return super.onKeyDown(keyCode, event); } /* (non-Javadoc) * @see android.app.Dialog#onKeyUp(int, android.view.KeyEvent) */ @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (! _justStarted && keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_MENU && getCurrentFocus()==null) { if (MetaKeyBean.keysByKeyCode.get(keyCode) != null) { sendCurrentKey(); dismiss(); } return true; } _justStarted = false; return super.onKeyUp(keyCode, event); } @SuppressWarnings("unchecked") private static ArrayAdapter<String> getSpinnerAdapter(Spinner spinner) { return (ArrayAdapter<String>)spinner.getAdapter(); } void sendCurrentKey() { int index = Collections.binarySearch(_keysInList, _currentKeyBean); SQLiteDatabase db = _database.getWritableDatabase(); if (index < 0) { int insertionPoint = -(index + 1); _currentKeyBean.Gen_insert(db); _keysInList.add(insertionPoint,_currentKeyBean); getSpinnerAdapter(_spinnerKeysInList).insert(_currentKeyBean.getKeyDesc(), insertionPoint); _spinnerKeysInList.setSelection(insertionPoint); _connection.setLastMetaKeyId(_currentKeyBean.get_Id()); } else { MetaKeyBean bean = _keysInList.get(index); _connection.setLastMetaKeyId(bean.get_Id()); _spinnerKeysInList.setSelection(index); } _connection.Gen_update(db); _canvasActivity.vncCanvas.sendMetaKey(_currentKeyBean); } void setMetaKeyList() { long listId = _connection.getMetaListId(); if (listId!=_listId) { for (int i=0; i<_lists.size(); ++i) { MetaList list = _lists.get(i); if (list.get_Id()==listId) { _spinnerLists.setSelection(i); _keysInList = new ArrayList<MetaKeyBean>(); Cursor c = _database.getReadableDatabase().rawQuery( MessageFormat.format("SELECT * FROM {0} WHERE {1} = {2} ORDER BY KEYDESC", MetaKeyBean.GEN_TABLE_NAME, MetaKeyBean.GEN_FIELD_METALISTID, listId), EMPTY_ARGS); MetaKeyBean.Gen_populateFromCursor( c, _keysInList, MetaKeyBean.NEW); c.close(); ArrayList<String> keys = new ArrayList<String>(_keysInList.size()); int selectedOffset = 0; long lastSelectedKeyId = _canvasActivity.getConnection().getLastMetaKeyId(); for (int j=0; j<_keysInList.size(); j++) { MetaKeyBean key = _keysInList.get(j); keys.add( key.getKeyDesc()); if (lastSelectedKeyId==key.get_Id()) { selectedOffset = j; } } _spinnerKeysInList.setAdapter(new ArrayAdapter<String>(getOwnerActivity(), android.R.layout.simple_spinner_item, keys)); if (keys.size()>0) { _spinnerKeysInList.setSelection(selectedOffset); _currentKeyBean = new MetaKeyBean(_keysInList.get(selectedOffset)); } else { _currentKeyBean = new MetaKeyBean(listId, 0, MetaKeyBean.allKeys.get(0)); } updateDialogForCurrentKey(); _textListName.setText(list.getName()); break; } } _listId = listId; } } private void updateDialogForCurrentKey() { int flags = _currentKeyBean.getMetaFlags(); _checkAlt.setChecked(0 != (flags & VncCanvas.ALT_MASK)); _checkShift.setChecked(0 != (flags & VncCanvas.SHIFT_MASK)); _checkCtrl.setChecked(0 != (flags & VncCanvas.CTRL_MASK)); MetaKeyBase base = null; if (_currentKeyBean.isMouseClick()) { base = MetaKeyBean.keysByMouseButton.get(_currentKeyBean.getMouseButtons()); } else { base = MetaKeyBean.keysByKeySym.get(_currentKeyBean.getKeySym()); } if (base != null) { int index = Collections.binarySearch(MetaKeyBean.allKeys,base); if (index >= 0) { _spinnerKeySelect.setSelection(index); } } _textKeyDesc.setText(_currentKeyBean.getKeyDesc()); } public void setConnection(ConnectionBean conn) { if ( _connection != conn) { _connection = conn; setMetaKeyList(); } } void setListSpinner() { ArrayList<String> listNames = new ArrayList<String>(_lists.size()); for (int i=0; i<_lists.size(); ++i) { MetaList l = _lists.get(i); listNames.add(l.getName()); } _spinnerLists.setAdapter(new ArrayAdapter<String>(getOwnerActivity(),android.R.layout.simple_spinner_item, listNames)); } /** * @author Michael A. MacDonald * */ class MetaCheckListener implements OnCheckedChangeListener { private int _mask; MetaCheckListener(int mask) { _mask = mask; } /* (non-Javadoc) * @see android.widget.CompoundButton.OnCheckedChangeListener#onCheckedChanged(android.widget.CompoundButton, boolean) */ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { _currentKeyBean.setMetaFlags(_currentKeyBean.getMetaFlags() | _mask); } else { _currentKeyBean.setMetaFlags(_currentKeyBean.getMetaFlags() & ~_mask); } _textKeyDesc.setText(_currentKeyBean.getKeyDesc()); } } }