Example #1
0
		/// <summary>React to the user typing while in the suggestions list.</summary>
		/// <remarks>
		/// React to the user typing while in the suggestions list. First, check for
		/// action keys. If not handled, try refocusing regular characters into the
		/// EditText.
		/// </remarks>
		private bool onSuggestionsKey(android.view.View v, int keyCode, android.view.KeyEvent
			 @event)
		{
			// guard against possible race conditions (late arrival after dismiss)
			if (mSearchable == null)
			{
				return false;
			}
			if (mSuggestionsAdapter == null)
			{
				return false;
			}
			if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.hasNoModifiers
				())
			{
				// First, check for enter or search (both of which we'll treat as a
				// "click")
				if (keyCode == android.view.KeyEvent.KEYCODE_ENTER || keyCode == android.view.KeyEvent
					.KEYCODE_SEARCH || keyCode == android.view.KeyEvent.KEYCODE_TAB)
				{
					int position = mQueryTextView.getListSelection();
					return onItemClicked(position, android.view.KeyEvent.KEYCODE_UNKNOWN, null);
				}
				// Next, check for left/right moves, which we use to "return" the
				// user to the edit view
				if (keyCode == android.view.KeyEvent.KEYCODE_DPAD_LEFT || keyCode == android.view.KeyEvent
					.KEYCODE_DPAD_RIGHT)
				{
					// give "focus" to text editor, with cursor at the beginning if
					// left key, at end if right key
					// TODO: Reverse left/right for right-to-left languages, e.g.
					// Arabic
					int selPoint = (keyCode == android.view.KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView
						.length();
					mQueryTextView.setSelection(selPoint);
					mQueryTextView.setListSelection(0);
					mQueryTextView.clearListSelection();
					mQueryTextView.ensureImeVisible(true);
					return true;
				}
				// Next, check for an "up and out" move
				if (keyCode == android.view.KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection
					())
				{
					// TODO: restoreUserQuery();
					// let ACTV complete the move
					return false;
				}
				// Next, check for an "action key"
				android.app.SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode
					);
				if ((actionKey != null) && ((actionKey.getSuggestActionMsg() != null) || (actionKey
					.getSuggestActionMsgColumn() != null)))
				{
					// launch suggestion using action key column
					int position = mQueryTextView.getListSelection();
					if (position != android.widget.AdapterView.INVALID_POSITION)
					{
						android.database.Cursor c = mSuggestionsAdapter.getCursor();
						if (c.moveToPosition(position))
						{
							string actionMsg = getActionKeyMessage(c, actionKey);
							if (actionMsg != null && (actionMsg.Length > 0))
							{
								return onItemClicked(position, keyCode, actionMsg);
							}
						}
					}
				}
			}
			return false;
		}
Example #2
0
		public override bool onKeyDown(android.view.View view, android.text.Editable content
			, int keyCode, android.view.KeyEvent @event)
		{
			int selStart;
			int selEnd;
			int pref = 0;
			if (view != null)
			{
				pref = android.text.method.TextKeyListener.getInstance().getPrefs(view.getContext
					());
			}
			{
				int a = android.text.Selection.getSelectionStart(content);
				int b = android.text.Selection.getSelectionEnd(content);
				selStart = System.Math.Min(a, b);
				selEnd = System.Math.Max(a, b);
				if (selStart < 0 || selEnd < 0)
				{
					selStart = selEnd = 0;
					android.text.Selection.setSelection(content, 0, 0);
				}
			}
			int activeStart = content.getSpanStart(android.text.method.TextKeyListener.ACTIVE
				);
			int activeEnd = content.getSpanEnd(android.text.method.TextKeyListener.ACTIVE);
			// QWERTY keyboard normal case
			int i = @event.getUnicodeChar(@event.getMetaState() | getMetaState(content));
			if (!mFullKeyboard)
			{
				int count = @event.getRepeatCount();
				if (count > 0 && selStart == selEnd && selStart > 0)
				{
					char c = content[selStart - 1];
					if (c == i || c == Sharpen.CharHelper.ToUpper(i) && view != null)
					{
						if (showCharacterPicker(view, content, c, false, count))
						{
							resetMetaState(content);
							return true;
						}
					}
				}
			}
			if (i == android.view.KeyCharacterMap.PICKER_DIALOG_INPUT)
			{
				if (view != null)
				{
					showCharacterPicker(view, content, android.view.KeyCharacterMap.PICKER_DIALOG_INPUT
						, true, 1);
				}
				resetMetaState(content);
				return true;
			}
			if (i == android.view.KeyCharacterMap.HEX_INPUT)
			{
				int start;
				if (selStart == selEnd)
				{
					start = selEnd;
					while (start > 0 && selEnd - start < 4 && Sharpen.CharHelper.Digit(content[start 
						- 1], 16) >= 0)
					{
						start--;
					}
				}
				else
				{
					start = selStart;
				}
				int ch = -1;
				try
				{
					string hex = android.text.TextUtils.substring(content, start, selEnd);
					ch = System.Convert.ToInt32(hex, 16);
				}
				catch (System.ArgumentException)
				{
				}
				if (ch >= 0)
				{
					selStart = start;
					android.text.Selection.setSelection(content, selStart, selEnd);
					i = ch;
				}
				else
				{
					i = 0;
				}
			}
			if (i != 0)
			{
				bool dead = false;
				if ((i & android.view.KeyCharacterMap.COMBINING_ACCENT) != 0)
				{
					dead = true;
					i = i & android.view.KeyCharacterMap.COMBINING_ACCENT_MASK;
				}
				if (activeStart == selStart && activeEnd == selEnd)
				{
					bool replace = false;
					if (selEnd - selStart - 1 == 0)
					{
						char accent = content[selStart];
						int composed = android.view.KeyEvent.getDeadChar(accent, i);
						if (composed != 0)
						{
							i = composed;
							replace = true;
						}
					}
					if (!replace)
					{
						android.text.Selection.setSelection(content, selEnd);
						content.removeSpan(android.text.method.TextKeyListener.ACTIVE);
						selStart = selEnd;
					}
				}
				if ((pref & android.text.method.TextKeyListener.AUTO_CAP) != 0 && Sharpen.CharHelper.IsLower
					(i) && android.text.method.TextKeyListener.shouldCap(mAutoCap, content, selStart
					))
				{
					int where = content.getSpanEnd(android.text.method.TextKeyListener.CAPPED);
					int flags = content.getSpanFlags(android.text.method.TextKeyListener.CAPPED);
					if (where == selStart && (((flags >> 16) & unchecked((int)(0xFFFF))) == i))
					{
						content.removeSpan(android.text.method.TextKeyListener.CAPPED);
					}
					else
					{
						flags = i << 16;
						i = Sharpen.CharHelper.ToUpper(i);
						if (selStart == 0)
						{
							content.setSpan(android.text.method.TextKeyListener.CAPPED, 0, 0, android.text.SpannedClass.SPAN_MARK_MARK
								 | flags);
						}
						else
						{
							content.setSpan(android.text.method.TextKeyListener.CAPPED, selStart - 1, selStart
								, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE | flags);
						}
					}
				}
				if (selStart != selEnd)
				{
					android.text.Selection.setSelection(content, selEnd);
				}
				content.setSpan(OLD_SEL_START, selStart, selStart, android.text.SpannedClass.SPAN_MARK_MARK
					);
				content.replace(selStart, selEnd, java.lang.CharSequenceProxy.Wrap(((char)i).ToString
					()));
				int oldStart = content.getSpanStart(OLD_SEL_START);
				selEnd = android.text.Selection.getSelectionEnd(content);
				if (oldStart < selEnd)
				{
					content.setSpan(android.text.method.TextKeyListener.LAST_TYPED, oldStart, selEnd, 
						android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
					if (dead)
					{
						android.text.Selection.setSelection(content, oldStart, selEnd);
						content.setSpan(android.text.method.TextKeyListener.ACTIVE, oldStart, selEnd, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE
							);
					}
				}
				adjustMetaAfterKeypress(content);
				// potentially do autotext replacement if the character
				// that was typed was an autotext terminator
				if ((pref & android.text.method.TextKeyListener.AUTO_TEXT) != 0 && mAutoText && (
					i == ' ' || i == '\t' || i == '\n' || i == ',' || i == '.' || i == '!' || i == '?'
					 || i == '"' || Sharpen.CharHelper.GetType(i) == Sharpen.CharHelper.END_PUNCTUATION
					) && content.getSpanEnd(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT)
					 != oldStart)
				{
					int x;
					for (x = oldStart; x > 0; x--)
					{
						char c = content[x - 1];
						if (c != '\'' && !System.Char.IsLetter(c))
						{
							break;
						}
					}
					string rep = getReplacement(content, x, oldStart, view);
					if (rep != null)
					{
						android.text.method.QwertyKeyListener.Replaced[] repl = content.getSpans<android.text.method.QwertyKeyListener
							.Replaced>(0, content.Length);
						{
							for (int a = 0; a < repl.Length; a++)
							{
								content.removeSpan(repl[a]);
							}
						}
						char[] orig = new char[oldStart - x];
						android.text.TextUtils.getChars(content, x, oldStart, orig, 0);
						content.setSpan(new android.text.method.QwertyKeyListener.Replaced(orig), x, oldStart
							, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
						content.replace(x, oldStart, java.lang.CharSequenceProxy.Wrap(rep));
					}
				}
				// Replace two spaces by a period and a space.
				if ((pref & android.text.method.TextKeyListener.AUTO_PERIOD) != 0 && mAutoText)
				{
					selEnd = android.text.Selection.getSelectionEnd(content);
					if (selEnd - 3 >= 0)
					{
						if (content[selEnd - 1] == ' ' && content[selEnd - 2] == ' ')
						{
							char c = content[selEnd - 3];
							{
								for (int j = selEnd - 3; j > 0; j--)
								{
									if (c == '"' || Sharpen.CharHelper.GetType(c) == Sharpen.CharHelper.END_PUNCTUATION)
									{
										c = content[j - 1];
									}
									else
									{
										break;
									}
								}
							}
							if (System.Char.IsLetter(c) || System.Char.IsDigit(c))
							{
								content.replace(selEnd - 2, selEnd - 1, java.lang.CharSequenceProxy.Wrap("."));
							}
						}
					}
				}
				return true;
			}
			else
			{
				if (keyCode == android.view.KeyEvent.KEYCODE_DEL && (@event.hasNoModifiers() || @event
					.hasModifiers(android.view.KeyEvent.META_ALT_ON)) && selStart == selEnd)
				{
					// special backspace case for undoing autotext
					int consider = 1;
					// if backspacing over the last typed character,
					// it undoes the autotext prior to that character
					// (unless the character typed was newline, in which
					// case this behavior would be confusing)
					if (content.getSpanEnd(android.text.method.TextKeyListener.LAST_TYPED) == selStart)
					{
						if (content[selStart - 1] != '\n')
						{
							consider = 2;
						}
					}
					android.text.method.QwertyKeyListener.Replaced[] repl = content.getSpans<android.text.method.QwertyKeyListener
						.Replaced>(selStart - consider, selStart);
					if (repl.Length > 0)
					{
						int st = content.getSpanStart(repl[0]);
						int en = content.getSpanEnd(repl[0]);
						string old = new string(repl[0].mText);
						content.removeSpan(repl[0]);
						// only cancel the autocomplete if the cursor is at the end of
						// the replaced span (or after it, because the user is
						// backspacing over the space after the word, not the word
						// itself).
						if (selStart >= en)
						{
							content.setSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT, en, en, 
								android.text.SpannedClass.SPAN_POINT_POINT);
							content.replace(st, en, java.lang.CharSequenceProxy.Wrap(old));
							en = content.getSpanStart(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT
								);
							if (en - 1 >= 0)
							{
								content.setSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT, en - 1, 
									en, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
							}
							else
							{
								content.removeSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT);
							}
							adjustMetaAfterKeypress(content);
						}
						else
						{
							adjustMetaAfterKeypress(content);
							return base.onKeyDown(view, content, keyCode, @event);
						}
						return true;
					}
				}
			}
			return base.onKeyDown(view, content, keyCode, @event);
		}
Example #3
0
			public bool onKey(android.view.View v, int keyCode, android.view.KeyEvent @event)
			{
				// guard against possible race conditions
				if (this._enclosing.mSearchable == null)
				{
					return false;
				}
				// If a suggestion is selected, handle enter, search key, and action keys
				// as presses on the selected suggestion
				if (this._enclosing.mQueryTextView.isPopupShowing() && this._enclosing.mQueryTextView
					.getListSelection() != android.widget.AdapterView.INVALID_POSITION)
				{
					return this._enclosing.onSuggestionsKey(v, keyCode, @event);
				}
				// If there is text in the query box, handle enter, and action keys
				// The search key is handled by the dialog's onKeyDown().
				if (!this._enclosing.mQueryTextView.isEmpty() && @event.hasNoModifiers())
				{
					if (@event.getAction() == android.view.KeyEvent.ACTION_UP)
					{
						if (keyCode == android.view.KeyEvent.KEYCODE_ENTER)
						{
							v.cancelLongPress();
							// Launch as a regular search.
							this._enclosing.launchQuerySearch(android.view.KeyEvent.KEYCODE_UNKNOWN, null, ((
								android.text.Editable)this._enclosing.mQueryTextView.getText()).ToString());
							return true;
						}
					}
					if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN)
					{
						android.app.SearchableInfo.ActionKeyInfo actionKey = this._enclosing.mSearchable.
							findActionKey(keyCode);
						if ((actionKey != null) && (actionKey.getQueryActionMsg() != null))
						{
							this._enclosing.launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), ((android.text.Editable
								)this._enclosing.mQueryTextView.getText()).ToString());
							return true;
						}
					}
				}
				return false;
			}
Example #4
0
		private bool commonKey(int keyCode, int count, android.view.KeyEvent @event)
		{
			if (mAdapter == null)
			{
				return false;
			}
			if (mDataChanged)
			{
				layoutChildren();
			}
			bool handled = false;
			int action = @event.getAction();
			if (action != android.view.KeyEvent.ACTION_UP)
			{
				switch (keyCode)
				{
					case android.view.KeyEvent.KEYCODE_DPAD_LEFT:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_LEFT);
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_DPAD_RIGHT:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_RIGHT);
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_DPAD_UP:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_UP);
						}
						else
						{
							if (@event.hasModifiers(android.view.KeyEvent.META_ALT_ON))
							{
								handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_DPAD_DOWN:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_DOWN);
						}
						else
						{
							if (@event.hasModifiers(android.view.KeyEvent.META_ALT_ON))
							{
								handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_DPAD_CENTER:
					case android.view.KeyEvent.KEYCODE_ENTER:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded();
							if (!handled && @event.getRepeatCount() == 0 && getChildCount() > 0)
							{
								keyPressed();
								handled = true;
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_SPACE:
					{
						if (mPopup == null || !mPopup.isShowing())
						{
							if (@event.hasNoModifiers())
							{
								handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
							}
							else
							{
								if (@event.hasModifiers(android.view.KeyEvent.META_SHIFT_ON))
								{
									handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
								}
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_PAGE_UP:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
						}
						else
						{
							if (@event.hasModifiers(android.view.KeyEvent.META_ALT_ON))
							{
								handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_PAGE_DOWN:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
						}
						else
						{
							if (@event.hasModifiers(android.view.KeyEvent.META_ALT_ON))
							{
								handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
							}
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_MOVE_HOME:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_MOVE_END:
					{
						if (@event.hasNoModifiers())
						{
							handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
						}
						break;
					}

					case android.view.KeyEvent.KEYCODE_TAB:
					{
						// XXX Sometimes it is useful to be able to TAB through the items in
						//     a GridView sequentially.  Unfortunately this can create an
						//     asymmetry in TAB navigation order unless the list selection
						//     always reverts to the top or bottom when receiving TAB focus from
						//     another widget.  Leaving this behavior disabled for now but
						//     perhaps it should be configurable (and more comprehensive).
						if (false)
						{
							if (@event.hasNoModifiers())
							{
								handled = resurrectSelectionIfNeeded() || sequenceScroll(FOCUS_FORWARD);
							}
							else
							{
								if (@event.hasModifiers(android.view.KeyEvent.META_SHIFT_ON))
								{
									handled = resurrectSelectionIfNeeded() || sequenceScroll(FOCUS_BACKWARD);
								}
							}
						}
						break;
					}
				}
			}
			if (handled)
			{
				return true;
			}
			if (sendToTextFilter(keyCode, count, @event))
			{
				return true;
			}
			switch (action)
			{
				case android.view.KeyEvent.ACTION_DOWN:
				{
					return base.onKeyDown(keyCode, @event);
				}

				case android.view.KeyEvent.ACTION_UP:
				{
					return base.onKeyUp(keyCode, @event);
				}

				case android.view.KeyEvent.ACTION_MULTIPLE:
				{
					return base.onKeyMultiple(keyCode, count, @event);
				}

				default:
				{
					return false;
				}
			}
		}