|
|
@ -10,9 +10,12 @@ import android.support.annotation.Nullable; |
|
|
|
import android.support.design.widget.TextInputEditText; |
|
|
|
import android.support.design.widget.TextInputLayout; |
|
|
|
import android.support.v7.widget.AppCompatImageButton; |
|
|
|
import android.support.v7.widget.GridLayoutManager; |
|
|
|
import android.support.v7.widget.RecyclerView; |
|
|
|
import android.text.Editable; |
|
|
|
import android.text.TextUtils; |
|
|
|
import android.util.AttributeSet; |
|
|
|
import android.util.DisplayMetrics; |
|
|
|
import android.util.SparseArray; |
|
|
|
import android.view.LayoutInflater; |
|
|
|
import android.view.inputmethod.EditorInfo; |
|
|
@ -80,47 +83,6 @@ public class EditorView extends LinearLayout { |
|
|
|
return false; |
|
|
|
}); |
|
|
|
|
|
|
|
emojiButton.setOnClickListener(view -> { |
|
|
|
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); |
|
|
|
assert imm != null; |
|
|
|
if (emojiKeyboardOwner.isEmojiKeyboardVisible()) { |
|
|
|
editText.requestFocus(); |
|
|
|
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); |
|
|
|
emojiButton.setImageResource(R.drawable.ic_tag_faces_24dp); |
|
|
|
} else { |
|
|
|
imm.hideSoftInputFromWindow(getWindowToken(), 0); |
|
|
|
view.clearFocus(); |
|
|
|
emojiButton.setImageResource(R.drawable.ic_keyboard_24dp); |
|
|
|
} |
|
|
|
emojiKeyboardOwner.setEmojiKeyboardVisible(!emojiKeyboardOwner.isEmojiKeyboardVisible()); |
|
|
|
}); |
|
|
|
|
|
|
|
submitButton = findViewById(R.id.submit_button); |
|
|
|
findViewById(R.id.bold_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[b]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/b]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
}); |
|
|
|
findViewById(R.id.italic_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[i]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/i]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
}); |
|
|
|
findViewById(R.id.underline_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[u]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/u]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
}); |
|
|
|
findViewById(R.id.strikethrough_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[s]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/s]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
}); |
|
|
|
|
|
|
|
colors.append(R.id.black, "black"); |
|
|
|
colors.append(R.id.red, "red"); |
|
|
|
colors.append(R.id.yellow, "yellow"); |
|
|
@ -136,114 +98,181 @@ public class EditorView extends LinearLayout { |
|
|
|
colors.append(R.id.maroon, "maroon"); |
|
|
|
colors.append(R.id.lime_green, "limegreen"); |
|
|
|
|
|
|
|
findViewById(R.id.text_color_button).setOnClickListener(view -> { |
|
|
|
PopupWindow popupWindow = new PopupWindow(view.getContext()); |
|
|
|
popupWindow.setHeight(LayoutParams.WRAP_CONTENT); |
|
|
|
popupWindow.setWidth(LayoutParams.WRAP_CONTENT); |
|
|
|
popupWindow.setFocusable(true); |
|
|
|
ScrollView colorPickerScrollview = (ScrollView) LayoutInflater.from(context).inflate(R.layout.editor_view_color_picker, null); |
|
|
|
LinearLayout colorPicker = (LinearLayout) colorPickerScrollview.getChildAt(0); |
|
|
|
popupWindow.setContentView(colorPickerScrollview); |
|
|
|
for (int i = 0; i < colorPicker.getChildCount(); i++) { |
|
|
|
TextView child = (TextView) colorPicker.getChildAt(i); |
|
|
|
child.setOnClickListener(v -> { |
|
|
|
RecyclerView formatButtonsRecyclerview = findViewById(R.id.buttons_recyclerview); |
|
|
|
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); |
|
|
|
float itemWidth = getResources().getDimension(R.dimen.editor_format_button_size) + |
|
|
|
getResources().getDimension(R.dimen.editor_format_button_margin_between); |
|
|
|
int columns = (int) Math.floor(displayMetrics.widthPixels / itemWidth); |
|
|
|
formatButtonsRecyclerview.setLayoutManager(new GridLayoutManager(context, columns)); |
|
|
|
formatButtonsRecyclerview.setAdapter(new FormatButtonsAdapter((view, drawableId) -> { |
|
|
|
switch (drawableId) { |
|
|
|
case R.drawable.ic_format_bold: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[b]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/b]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_italic: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[i]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/i]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_underlined: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[u]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/u]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_strikethrough_s: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[color=" + colors.get(v.getId()) + "]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/color]"); |
|
|
|
getText().insert(editText.getSelectionStart(), "[s]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/s]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 4); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_color_text: { |
|
|
|
PopupWindow popupWindow = new PopupWindow(view.getContext()); |
|
|
|
popupWindow.setHeight(LayoutParams.WRAP_CONTENT); |
|
|
|
popupWindow.setWidth(LayoutParams.WRAP_CONTENT); |
|
|
|
popupWindow.setFocusable(true); |
|
|
|
ScrollView colorPickerScrollview = (ScrollView) LayoutInflater.from(context).inflate(R.layout.editor_view_color_picker, null); |
|
|
|
LinearLayout colorPicker = (LinearLayout) colorPickerScrollview.getChildAt(0); |
|
|
|
popupWindow.setContentView(colorPickerScrollview); |
|
|
|
for (int i = 0; i < colorPicker.getChildCount(); i++) { |
|
|
|
TextView child = (TextView) colorPicker.getChildAt(i); |
|
|
|
child.setOnClickListener(v -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[color=" + colors.get(v.getId()) + "]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/color]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 8); |
|
|
|
popupWindow.dismiss(); |
|
|
|
}); |
|
|
|
} |
|
|
|
popupWindow.showAsDropDown(view); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_size: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[size=10pt]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/size]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_text_format: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[font=Verdana]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/font]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_list_bulleted: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[list]\n[li]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/li]\n[li][/li]\n[/list]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() - 13 : editText.getSelectionStart() - 23); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_align_left: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[left]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/left]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_align_center: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[center]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/center]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 9); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_align_right: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[right]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/right]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 8); |
|
|
|
popupWindow.dismiss(); |
|
|
|
}); |
|
|
|
} |
|
|
|
popupWindow.showAsDropDown(view); |
|
|
|
}); |
|
|
|
findViewById(R.id.text_size_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[size=10pt]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/size]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
}); |
|
|
|
findViewById(R.id.font_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[font=Verdana]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/font]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
}); |
|
|
|
findViewById(R.id.unordered_list_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[list]\n[li]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/li]\n[li][/li]\n[/list]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() - 13 : editText.getSelectionStart() - 23); |
|
|
|
}); |
|
|
|
findViewById(R.id.align_left_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[left]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/left]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
}); |
|
|
|
findViewById(R.id.align_center_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[center]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/center]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 9); |
|
|
|
}); |
|
|
|
findViewById(R.id.align_right_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[right]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/right]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 8); |
|
|
|
}); |
|
|
|
findViewById(R.id.link_button).setOnClickListener(view -> { |
|
|
|
LinearLayout dialogBody = (LinearLayout) LayoutInflater.from(context) |
|
|
|
.inflate(R.layout.dialog_create_link, null); |
|
|
|
TextInputLayout linkUrl = dialogBody.findViewById(R.id.link_url_input); |
|
|
|
linkUrl.setOnClickListener(view1 -> linkUrl.setError(null)); |
|
|
|
TextInputLayout linkText = dialogBody.findViewById(R.id.link_text_input); |
|
|
|
linkText.setOnClickListener(view2 -> linkText.setError(null)); |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
int start = editText.getSelectionStart(), end = editText.getSelectionEnd(); |
|
|
|
if (editText.hasSelection()) { |
|
|
|
linkText.getEditText().setText( |
|
|
|
editText.getText().toString().substring(editText.getSelectionStart(), editText.getSelectionEnd())); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_insert_link: { |
|
|
|
LinearLayout dialogBody = (LinearLayout) LayoutInflater.from(context) |
|
|
|
.inflate(R.layout.dialog_create_link, null); |
|
|
|
TextInputLayout linkUrl = dialogBody.findViewById(R.id.link_url_input); |
|
|
|
linkUrl.setOnClickListener(view1 -> linkUrl.setError(null)); |
|
|
|
TextInputLayout linkText = dialogBody.findViewById(R.id.link_text_input); |
|
|
|
linkText.setOnClickListener(view2 -> linkText.setError(null)); |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
int start = editText.getSelectionStart(), end = editText.getSelectionEnd(); |
|
|
|
if (editText.hasSelection()) { |
|
|
|
linkText.getEditText().setText( |
|
|
|
editText.getText().toString().substring(editText.getSelectionStart(), editText.getSelectionEnd())); |
|
|
|
} |
|
|
|
new AlertDialog.Builder(context, R.style.AppTheme_Dark_Dialog) |
|
|
|
.setTitle(R.string.dialog_create_link_title) |
|
|
|
.setView(dialogBody) |
|
|
|
.setPositiveButton(R.string.ok, (dialog, which) -> { |
|
|
|
if (TextUtils.isEmpty(Objects.requireNonNull(linkUrl.getEditText()).getText().toString())) { |
|
|
|
linkUrl.setError(context.getString(R.string.input_field_required)); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (TextUtils.isEmpty(Objects.requireNonNull(linkText.getEditText()).getText().toString())) { |
|
|
|
linkUrl.setError(context.getString(R.string.input_field_required)); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (hadTextSelection) editText.getText().delete(start, end); |
|
|
|
getText().insert(editText.getSelectionStart(), "[url=" + |
|
|
|
Objects.requireNonNull(linkUrl.getEditText()).getText().toString() + "]" + |
|
|
|
Objects.requireNonNull(linkText.getEditText()).getText().toString() + "[/url]"); |
|
|
|
}) |
|
|
|
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()) |
|
|
|
.show(); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_format_quote: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[quote]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/quote]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 8); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_code: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[code]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/code]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
break; |
|
|
|
} |
|
|
|
case R.drawable.ic_functions: { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[tex]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/tex]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 6); |
|
|
|
break; |
|
|
|
} |
|
|
|
default: throw new IllegalArgumentException("Unknown format button click"); |
|
|
|
} |
|
|
|
new AlertDialog.Builder(context, R.style.AppTheme_Dark_Dialog) |
|
|
|
.setTitle(R.string.dialog_create_link_title) |
|
|
|
.setView(dialogBody) |
|
|
|
.setPositiveButton(R.string.ok, (dialog, which) -> { |
|
|
|
if (TextUtils.isEmpty(Objects.requireNonNull(linkUrl.getEditText()).getText().toString())) { |
|
|
|
linkUrl.setError(context.getString(R.string.input_field_required)); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (TextUtils.isEmpty(Objects.requireNonNull(linkText.getEditText()).getText().toString())) { |
|
|
|
linkUrl.setError(context.getString(R.string.input_field_required)); |
|
|
|
return; |
|
|
|
} |
|
|
|
})); |
|
|
|
|
|
|
|
if (hadTextSelection) editText.getText().delete(start, end); |
|
|
|
getText().insert(editText.getSelectionStart(), "[url=" + |
|
|
|
Objects.requireNonNull(linkUrl.getEditText()).getText().toString() + "]" + |
|
|
|
Objects.requireNonNull(linkText.getEditText()).getText().toString() + "[/url]"); |
|
|
|
}) |
|
|
|
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()) |
|
|
|
.show(); |
|
|
|
}); |
|
|
|
findViewById(R.id.quote_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[quote]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/quote]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 8); |
|
|
|
}); |
|
|
|
findViewById(R.id.code_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[code]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/code]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 7); |
|
|
|
}); |
|
|
|
findViewById(R.id.math_button).setOnClickListener(view -> { |
|
|
|
boolean hadTextSelection = editText.hasSelection(); |
|
|
|
getText().insert(editText.getSelectionStart(), "[tex]"); |
|
|
|
getText().insert(editText.getSelectionEnd(), "[/tex]"); |
|
|
|
editText.setSelection(hadTextSelection ? editText.getSelectionEnd() : editText.getSelectionStart() - 6); |
|
|
|
emojiButton.setOnClickListener(view -> { |
|
|
|
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); |
|
|
|
assert imm != null; |
|
|
|
if (emojiKeyboardOwner.isEmojiKeyboardVisible()) { |
|
|
|
editText.requestFocus(); |
|
|
|
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); |
|
|
|
emojiButton.setImageResource(R.drawable.ic_tag_faces_24dp); |
|
|
|
} else { |
|
|
|
imm.hideSoftInputFromWindow(getWindowToken(), 0); |
|
|
|
view.clearFocus(); |
|
|
|
emojiButton.setImageResource(R.drawable.ic_keyboard_24dp); |
|
|
|
} |
|
|
|
emojiKeyboardOwner.setEmojiKeyboardVisible(!emojiKeyboardOwner.isEmojiKeyboardVisible()); |
|
|
|
}); |
|
|
|
|
|
|
|
submitButton = findViewById(R.id.submit_button); |
|
|
|
} |
|
|
|
|
|
|
|
public TextInputEditText getEditText() { |
|
|
|