package ru.net.jimm.input; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; import jimm.Jimm; import jimm.Options; import jimm.comm.StringUtils; import jimmui.ContentActionListener; import jimmui.model.chat.ChatModel; import jimmui.view.base.SomeContent; import jimmui.view.chat.Chat; import jimm.modules.Emotions; import jimm.modules.Templates; import jimmui.view.smiles.SmilesContent; import ru.net.jimm.JimmActivity; import ru.net.jimm.R; /** * Created with IntelliJ IDEA. * <p/> * Date: 21.02.13 17:08 * * @author vladimir */ public class Input extends LinearLayout implements View.OnClickListener, View.OnLongClickListener { private EditText messageEditor; private volatile Chat owner; private static State state = new State(null); private int layout = 0; private boolean sendByEnter; public Input(Context context, AttributeSet attrs, int id) { super(context, attrs); updateInput(); setId(id); } public void updateInput() { boolean simple = Options.getBoolean(Options.OPTION_SIMPLE_INPUT); final int newLayout = simple ? R.layout.input_simple : R.layout.input; if (layout != newLayout) { JimmActivity activity = (JimmActivity) getContext(); activity.post(new Runnable() { @Override public void run() { layout = newLayout; init(); requestLayout(); } }); } } private void init() { removeAllViewsInLayout(); ((Activity)getContext()) .getLayoutInflater() .inflate(layout, this, true); messageEditor = (EditText) findViewById(R.id.messageText); messageEditor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); ImageButton smileButton = (ImageButton) findViewById(R.id.input_smile_button); smileButton.setOnClickListener(this); smileButton.setOnLongClickListener(this); ImageButton sendButton = (ImageButton) findViewById(R.id.input_send_button); sendByEnter = (null == sendButton); if (null != sendButton) { sendButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { send(); } }); } if (sendByEnter) { messageEditor.setImeOptions(EditorInfo.IME_ACTION_SEND); messageEditor.setOnEditorActionListener(enterListener); } messageEditor.addTextChangedListener(textWatcher); } @Override public void onClick(View view) { Emotions.selectEmotion(new ContentActionListener() { @Override public void action(final SomeContent canvas, int cmd) { ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { insert(" " + ((SmilesContent)canvas).getSelectedCode() + " "); showKeyboard(); } }); } }); } @Override public boolean onLongClick(View view) { Templates.getInstance().showTemplatesList(new ContentActionListener() { @Override public void action(SomeContent canvas, int cmd) { ((JimmActivity) getContext()).post(new Runnable() { @Override public void run() { insert(Templates.getInstance().getSelectedTemplate()); showKeyboard(); } }); } }); return true; } private void showKeyboard(View view) { Configuration conf = Resources.getSystem().getConfiguration(); if (conf.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_NO) { InputMethodManager keyboard = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); keyboard.showSoftInput(view, InputMethodManager.SHOW_FORCED | InputMethodManager.SHOW_IMPLICIT); } } public void hideKeyboard(View view) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } public void showKeyboard() { ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { messageEditor.requestFocus(); } }); ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { showKeyboard(messageEditor); } }); } private void send() { hideKeyboard(messageEditor); if (Jimm.getJimm().getDisplay().getCurrentDisplay() != owner) return; String message = getText(); ChatModel model = owner.getModel(); if (!model.getContact().isSingleUserContact() && message.endsWith(", ")) { message = ""; } if (!StringUtils.isEmpty(message)) { Jimm.getJimm().jimmModel.registerChat(model); model.getProtocol().sendMessage(model.getContact(), message, true); } resetText(); } public void setText(final String text) { ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { String t = null == text ? "" : text; if ((0 == t.length()) || !canAdd(t)) { messageEditor.setText(t); messageEditor.setSelection(t.length()); } else { insert(t); } } }); showKeyboard(); } public boolean canAdd(String what) { String text = getText(); if (0 == text.length()) return false; // more then one comma if (text.indexOf(',') != text.lastIndexOf(',')) return true; // replace one post number to another if (what.startsWith("#") && !text.contains(" ")) return false; return !text.endsWith(", "); } public void resetOwner() { this.owner = null; } public void setOwner(Chat owner) { if (this.owner != owner) { this.owner = owner; if (null != owner) { final State newState = state.is(owner.getModel()) ? state : new State(owner.getModel()); state = newState; String name = newState.ownerChatModel.getContact().isSingleUserContact() ? newState.ownerChatModel.getContact().getName() : null; final String hint = (null == name) ? getContext().getString(R.string.hint_message) : getContext().getString(R.string.hint_message_to, name); ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { messageEditor.setHint(hint); messageEditor.setText(newState.text); messageEditor.setSelection(newState.text.length()); } }); } } } public void resetText() { ((JimmActivity)getContext()).post(new Runnable() { @Override public void run() { messageEditor.setText(""); state.text = ""; } }); } public String getText() { return messageEditor.getText().toString(); } public boolean hasText() { return 0 < messageEditor.getText().length(); } public void insert(String text) { int start = messageEditor.getSelectionStart(); int end = messageEditor.getSelectionEnd(); messageEditor.getText().replace(Math.min(start, end), Math.max(start, end), text, 0, text.length()); } private boolean isDone(int actionId) { return (EditorInfo.IME_NULL == actionId) || (EditorInfo.IME_ACTION_DONE == actionId) || (EditorInfo.IME_ACTION_SEND == actionId); } private final TextView.OnEditorActionListener enterListener = new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView exampleView, int actionId, KeyEvent event) { if (isDone(actionId)) { if ((null == event) || (event.getAction() == KeyEvent.ACTION_DOWN)) { send(); return true; } } return false; } }; private TextWatcher textWatcher = new TextWatcher() { private String previousText; private int lineCount = 0; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { if (sendByEnter) { previousText = s.toString(); } } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (sendByEnter && (start + count <= s.length()) && (1 == count)) { boolean enter = ('\n' == s.charAt(start)); if (enter) { messageEditor.setText(previousText); messageEditor.setSelection(start); send(); } else { state.text = s; } } else { state.text = s; } if (lineCount != messageEditor.getLineCount()) { lineCount = messageEditor.getLineCount(); messageEditor.requestLayout(); } } @Override public void afterTextChanged(Editable editable) { } }; public Chat getOwner() { return owner; } private static class State { private ChatModel ownerChatModel; private CharSequence text; public State(ChatModel model) { this.ownerChatModel = model; text = ""; } public boolean is(ChatModel model) { return ownerChatModel == model; } } }