add more keys to clipboard toolbar

This commit is contained in:
Helium314 2023-12-21 21:57:53 +01:00
parent 461eb2a551
commit dfa3a568be
4 changed files with 117 additions and 101 deletions

View file

@ -15,6 +15,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import android.widget.LinearLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -47,7 +48,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private MainKeyboardView mKeyboardView; private MainKeyboardView mKeyboardView;
private EmojiPalettesView mEmojiPalettesView; private EmojiPalettesView mEmojiPalettesView;
private View mEmojiTabStripView; private View mEmojiTabStripView;
private View mClipboardStripView; private LinearLayout mClipboardStripView;
private View mSuggestionStripView; private View mSuggestionStripView;
private ClipboardHistoryView mClipboardHistoryView; private ClipboardHistoryView mClipboardHistoryView;
private LatinIME mLatinIME; private LatinIME mLatinIME;
@ -530,7 +531,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
return mEmojiTabStripView; return mEmojiTabStripView;
} }
public View getClipboardStrip() { public LinearLayout getClipboardStrip() {
return mClipboardStripView; return mClipboardStripView;
} }

View file

@ -24,6 +24,13 @@ import org.dslul.openboard.inputmethod.latin.common.ColorType
import org.dslul.openboard.inputmethod.latin.common.Constants import org.dslul.openboard.inputmethod.latin.common.Constants
import org.dslul.openboard.inputmethod.latin.settings.Settings import org.dslul.openboard.inputmethod.latin.settings.Settings
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils
import org.dslul.openboard.inputmethod.latin.utils.TAG_CLEAR_CLIPBOARD
import org.dslul.openboard.inputmethod.latin.utils.TAG_COPY
import org.dslul.openboard.inputmethod.latin.utils.TAG_LEFT
import org.dslul.openboard.inputmethod.latin.utils.TAG_RIGHT
import org.dslul.openboard.inputmethod.latin.utils.TAG_SELECT_ALL
import org.dslul.openboard.inputmethod.latin.utils.createToolbarKey
import org.dslul.openboard.inputmethod.latin.utils.getCodeForTag
class ClipboardHistoryView @JvmOverloads constructor( class ClipboardHistoryView @JvmOverloads constructor(
context: Context, context: Context,
@ -41,7 +48,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
private lateinit var clipboardRecyclerView: ClipboardHistoryRecyclerView private lateinit var clipboardRecyclerView: ClipboardHistoryRecyclerView
private lateinit var placeholderView: TextView private lateinit var placeholderView: TextView
private lateinit var alphabetKey: TextView private lateinit var alphabetKey: TextView
private lateinit var clearKey: ImageButton private val toolbarKeys = mutableListOf<ImageButton>()
private lateinit var clipboardAdapter: ClipboardAdapter private lateinit var clipboardAdapter: ClipboardAdapter
private lateinit var spacebar: View private lateinit var spacebar: View
private lateinit var deleteKey: ImageButton private lateinit var deleteKey: ImageButton
@ -57,8 +64,12 @@ class ClipboardHistoryView @JvmOverloads constructor(
val keyboardViewAttr = context.obtainStyledAttributes(attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView) val keyboardViewAttr = context.obtainStyledAttributes(attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView)
keyBackgroundId = keyboardViewAttr.getResourceId(R.styleable.KeyboardView_keyBackground, 0) keyBackgroundId = keyboardViewAttr.getResourceId(R.styleable.KeyboardView_keyBackground, 0)
functionalKeyBackgroundId = keyboardViewAttr.getResourceId(R.styleable.KeyboardView_functionalKeyBackground, keyBackgroundId) functionalKeyBackgroundId = keyboardViewAttr.getResourceId(R.styleable.KeyboardView_functionalKeyBackground, keyBackgroundId)
spacebarBackground = Settings.getInstance().current.mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.SPACE_BAR_BACKGROUND); spacebarBackground = Settings.getInstance().current.mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.SPACE_BAR_BACKGROUND)
keyboardViewAttr.recycle() keyboardViewAttr.recycle()
val keyboardAttr = context.obtainStyledAttributes(attrs, R.styleable.Keyboard, defStyle, R.style.SuggestionStripView)
val toolbarKeyTags = listOf(TAG_LEFT, TAG_RIGHT, TAG_COPY, TAG_SELECT_ALL, TAG_CLEAR_CLIPBOARD)
toolbarKeyTags.forEach { toolbarKeys.add(createToolbarKey(context, keyboardAttr, it)) }
keyboardAttr.recycle()
} }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
@ -104,12 +115,14 @@ class ClipboardHistoryView @JvmOverloads constructor(
spacebar.setOnClickListener(this) spacebar.setOnClickListener(this)
// todo: add more buttons, like select all, arrow keys, copy, clear (and maybe start/end select?) // todo: add more buttons, like select all, arrow keys, copy, clear (and maybe start/end select?)
val clipboardStrip = KeyboardSwitcher.getInstance().clipboardStrip val clipboardStrip = KeyboardSwitcher.getInstance().clipboardStrip
colors.setBackground(clipboardStrip, ColorType.EMOJI_CATEGORY_BACKGROUND) // todo: choose a color toolbarKeys.forEach {
clearKey = clipboardStrip.findViewById(R.id.clipboard_clear) clipboardStrip.addView(it)
clearKey.setOnTouchListener(this@ClipboardHistoryView) it.setOnTouchListener(this@ClipboardHistoryView)
clearKey.setOnClickListener(this@ClipboardHistoryView) it.setOnClickListener(this@ClipboardHistoryView)
colors.setColor(clearKey, ColorType.CLEAR_CLIPBOARD_HISTORY_KEY) colors.setColor(it, ColorType.CLEAR_CLIPBOARD_HISTORY_KEY)
colors.setBackground(clearKey, ColorType.CLEAR_CLIPBOARD_HISTORY_KEY) colors.setBackground(it, ColorType.CLEAR_CLIPBOARD_HISTORY_KEY)
}
colors.setBackground(clipboardStrip, ColorType.BACKGROUND)
} }
private fun setupAlphabetKey(key: TextView, label: String, params: KeyDrawParams) { private fun setupAlphabetKey(key: TextView, label: String, params: KeyDrawParams) {
@ -139,9 +152,10 @@ class ClipboardHistoryView @JvmOverloads constructor(
} }
} }
private fun setupClearKey(iconSet: KeyboardIconsSet) { private fun setupToolbarKeys() {
val resId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_CLEAR_CLIPBOARD_KEY) // set layout params
clearKey.setImageResource(resId) val toolbarKeyLayoutParams = LayoutParams(getResources().getDimensionPixelSize(R.dimen.config_suggestions_strip_edge_key_width), LayoutParams.MATCH_PARENT)
toolbarKeys.forEach { it.layoutParams = toolbarKeyLayoutParams }
} }
fun setHardwareAcceleratedDrawingEnabled(enabled: Boolean) { fun setHardwareAcceleratedDrawingEnabled(enabled: Boolean) {
@ -156,6 +170,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
keyVisualAttr: KeyVisualAttributes?, keyVisualAttr: KeyVisualAttributes?,
iconSet: KeyboardIconsSet iconSet: KeyboardIconsSet
) { ) {
setupToolbarKeys()
historyManager.prepareClipboardHistory() historyManager.prepareClipboardHistory()
historyManager.setHistoryChangeListener(this) historyManager.setHistoryChangeListener(this)
clipboardHistoryManager = historyManager clipboardHistoryManager = historyManager
@ -169,7 +184,6 @@ class ClipboardHistoryView @JvmOverloads constructor(
setupAlphabetKey(alphabetKey, switchToAlphaLabel, params) setupAlphabetKey(alphabetKey, switchToAlphaLabel, params)
setupDeleteKey(deleteKey, iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY)) setupDeleteKey(deleteKey, iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY))
setupClipKey(params) setupClipKey(params)
setupClearKey(iconSet)
placeholderView.apply { placeholderView.apply {
typeface = params.mTypeface typeface = params.mTypeface
@ -197,7 +211,6 @@ class ClipboardHistoryView @JvmOverloads constructor(
} }
when (view) { when (view) {
alphabetKey, spacebar, deleteKey -> keyboardActionListener?.onPressKey(view.tag as Int, 0, true) alphabetKey, spacebar, deleteKey -> keyboardActionListener?.onPressKey(view.tag as Int, 0, true)
clearKey -> keyboardActionListener?.onPressKey(Constants.CODE_UNSPECIFIED, 0, true)
} }
// It's important to return false here. Otherwise, {@link #onClick} and touch-down visual // It's important to return false here. Otherwise, {@link #onClick} and touch-down visual
// feedback stop working. // feedback stop working.
@ -211,10 +224,16 @@ class ClipboardHistoryView @JvmOverloads constructor(
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false) Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false)
keyboardActionListener?.onReleaseKey(view.tag as Int, false) keyboardActionListener?.onReleaseKey(view.tag as Int, false)
} }
clearKey -> { }
clipboardHistoryManager?.clearHistory() val tag = view.tag
keyboardActionListener?.onReleaseKey(Constants.CODE_UNSPECIFIED, false) if (tag is String) {
val code = getCodeForTag(tag)
if (code != null) {
keyboardActionListener?.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false)
return
} }
if (tag == TAG_CLEAR_CLIPBOARD)
clipboardHistoryManager?.clearHistory()
} }
} }

View file

@ -6,6 +6,8 @@
package org.dslul.openboard.inputmethod.latin.suggestions; package org.dslul.openboard.inputmethod.latin.suggestions;
import static org.dslul.openboard.inputmethod.latin.utils.ToolbarUtilsKt.*;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.ClipData; import android.content.ClipData;
@ -34,7 +36,6 @@ import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
@ -76,18 +77,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
public static boolean DEBUG_SUGGESTIONS; public static boolean DEBUG_SUGGESTIONS;
private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.5f; private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.5f;
private static final String TAG_VOICE = "voice_key";
private static final String TAG_CLIPBOARD = "clipboard_key";
private static final String TAG_SETTINGS = "settings_key";
private static final String TAG_SELECT_ALL = "select_all_key";
private static final String TAG_COPY = "copy_key";
private static final String TAG_ONE_HANDED = "one_handed_key";
private static final String TAG_LEFT = "left_key";
private static final String TAG_RIGHT = "right_key";
private static final String TAG_UP = "up_key";
private static final String TAG_DOWN = "down_key";
private static final String TAG_REDO = "undo";
private static final String TAG_UNDO = "redo";
// tags of keys to be added to toolbar, in order (all tags must be considered in getStyleableIconId) // tags of keys to be added to toolbar, in order (all tags must be considered in getStyleableIconId)
private static final String[] toolbarKeyTags = new String[] {TAG_VOICE, TAG_CLIPBOARD, private static final String[] toolbarKeyTags = new String[] {TAG_VOICE, TAG_CLIPBOARD,
TAG_SELECT_ALL, TAG_COPY, TAG_UNDO, TAG_REDO, TAG_ONE_HANDED, TAG_SETTINGS, TAG_SELECT_ALL, TAG_COPY, TAG_UNDO, TAG_REDO, TAG_ONE_HANDED, TAG_SETTINGS,
@ -151,8 +140,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
this(context, attrs, R.attr.suggestionStripViewStyle); this(context, attrs, R.attr.suggestionStripViewStyle);
} }
public SuggestionStripView(final Context context, final AttributeSet attrs, public SuggestionStripView(final Context context, final AttributeSet attrs, final int defStyle) {
final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
final Colors colors = Settings.getInstance().getCurrent().mColors; final Colors colors = Settings.getInstance().getCurrent().mColors;
DEBUG_SUGGESTIONS = DeviceProtectedUtils.getSharedPreferences(context).getBoolean(DebugSettings.PREF_SHOW_SUGGESTION_INFOS, false); DEBUG_SUGGESTIONS = DeviceProtectedUtils.getSharedPreferences(context).getBoolean(DebugSettings.PREF_SHOW_SUGGESTION_INFOS, false);
@ -203,18 +191,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
LinearLayout.LayoutParams.MATCH_PARENT LinearLayout.LayoutParams.MATCH_PARENT
); );
for (final String tag : toolbarKeyTags) { for (final String tag : toolbarKeyTags) {
final ImageButton button = new ImageButton(getContext(), null, R.attr.suggestionWordStyle); final ImageButton button = createToolbarKey(context, keyboardAttr, tag);
button.setScaleType(ImageView.ScaleType.CENTER);
button.setLayoutParams(toolbarKeyLayoutParams); button.setLayoutParams(toolbarKeyLayoutParams);
button.setTag(tag);
final Drawable icon = keyboardAttr.getDrawable(getStyleableIconId(tag));
if (tag.equals(TAG_LEFT) || tag.equals(TAG_RIGHT) || tag.equals(TAG_UP) || tag.equals(TAG_DOWN)) {
// arrows look a little awkward when not scaled
button.setScaleX(1.2f);
button.setScaleY(1.2f);
}
button.setImageDrawable(icon);
setupKey(button, colors);
mToolbar.addView(button); mToolbar.addView(button);
} }
keyboardAttr.recycle(); keyboardAttr.recycle();
@ -625,45 +603,10 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(Constants.CODE_UNSPECIFIED, this); AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(Constants.CODE_UNSPECIFIED, this);
final Object tag = view.getTag(); final Object tag = view.getTag();
if (tag instanceof String) { if (tag instanceof String) {
switch ((String) tag) { final Integer code = getCodeForTag((String) tag);
case TAG_VOICE: if (code != null) {
mListener.onCodeInput(Constants.CODE_SHORTCUT, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false); mListener.onCodeInput(code, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return; return;
case TAG_CLIPBOARD:
mListener.onCodeInput(Constants.CODE_CLIPBOARD, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_SELECT_ALL:
mListener.onCodeInput(Constants.CODE_SELECT_ALL, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_COPY:
mListener.onCodeInput(Constants.CODE_COPY, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_ONE_HANDED:
final boolean oneHandedEnabled = Settings.getInstance().getCurrent().mOneHandedModeEnabled;
mListener.onCodeInput(oneHandedEnabled ? Constants.CODE_STOP_ONE_HANDED_MODE : Constants.CODE_START_ONE_HANDED_MODE,
Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_SETTINGS:
mListener.onCodeInput(Constants.CODE_SETTINGS, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_LEFT:
mListener.onCodeInput(Constants.CODE_LEFT, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_RIGHT:
mListener.onCodeInput(Constants.CODE_RIGHT, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_UP:
mListener.onCodeInput(Constants.CODE_UP, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_DOWN:
mListener.onCodeInput(Constants.CODE_DOWN, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_UNDO:
mListener.onCodeInput(Constants.CODE_UNDO, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
case TAG_REDO:
mListener.onCodeInput(Constants.CODE_REDO, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
return;
} }
} }
if (view == mToolbarKey) { if (view == mToolbarKey) {
@ -730,22 +673,4 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
colors.setColor(view, ColorType.TOOL_BAR_KEY); colors.setColor(view, ColorType.TOOL_BAR_KEY);
colors.setBackground(view, ColorType.SUGGESTION_BACKGROUND); colors.setBackground(view, ColorType.SUGGESTION_BACKGROUND);
} }
private int getStyleableIconId(final String buttonTag) {
return switch (buttonTag) {
case TAG_VOICE -> R.styleable.Keyboard_iconShortcutKey;
case TAG_SETTINGS -> R.styleable.Keyboard_iconSettingsKey;
case TAG_CLIPBOARD -> R.styleable.Keyboard_iconClipboardNormalKey;
case TAG_SELECT_ALL -> R.styleable.Keyboard_iconSelectAll;
case TAG_COPY -> R.styleable.Keyboard_iconCopyKey;
case TAG_ONE_HANDED -> R.styleable.Keyboard_iconStartOneHandedMode;
case TAG_LEFT -> R.styleable.Keyboard_iconArrowLeft;
case TAG_RIGHT -> R.styleable.Keyboard_iconArrowRight;
case TAG_UP -> R.styleable.Keyboard_iconArrowUp;
case TAG_DOWN -> R.styleable.Keyboard_iconArrowDown;
case TAG_UNDO -> R.styleable.Keyboard_iconUndo;
case TAG_REDO -> R.styleable.Keyboard_iconRedo;
default -> throw (new IllegalArgumentException("no styleable id for " + buttonTag));
};
}
} }

View file

@ -0,0 +1,71 @@
package org.dslul.openboard.inputmethod.latin.utils
import android.content.Context
import android.content.res.TypedArray
import android.widget.ImageButton
import android.widget.ImageView
import org.dslul.openboard.inputmethod.latin.R
import org.dslul.openboard.inputmethod.latin.common.Constants.*
import org.dslul.openboard.inputmethod.latin.settings.Settings
fun createToolbarKey(context: Context, keyboardAttr: TypedArray, tag: String): ImageButton {
val button = ImageButton(context, null, R.attr.suggestionWordStyle)
button.scaleType = ImageView.ScaleType.CENTER
button.tag = tag
val icon = keyboardAttr.getDrawable(getStyleableIconId(tag))
if (tag == TAG_LEFT || tag == TAG_RIGHT || tag == TAG_UP || tag == TAG_DOWN) {
// arrows look a little awkward when not scaled
button.scaleX = 1.2f
button.scaleY = 1.2f
}
button.setImageDrawable(icon)
return button
}
fun getCodeForTag(tag: String) = when (tag) {
TAG_VOICE -> CODE_SHORTCUT
TAG_SETTINGS -> CODE_SETTINGS
TAG_CLIPBOARD -> CODE_CLIPBOARD
TAG_SELECT_ALL -> CODE_SELECT_ALL
TAG_COPY -> CODE_COPY
TAG_ONE_HANDED -> if (Settings.getInstance().current.mOneHandedModeEnabled) CODE_START_ONE_HANDED_MODE else CODE_STOP_ONE_HANDED_MODE
TAG_LEFT -> CODE_LEFT
TAG_RIGHT -> CODE_RIGHT
TAG_UP -> CODE_UP
TAG_DOWN -> CODE_DOWN
TAG_UNDO -> CODE_UNDO
TAG_REDO -> CODE_REDO
TAG_CLEAR_CLIPBOARD -> null // not managed via code input
else -> null
}
private fun getStyleableIconId(tag: String) = when (tag) {
TAG_VOICE -> R.styleable.Keyboard_iconShortcutKey
TAG_SETTINGS -> R.styleable.Keyboard_iconSettingsKey
TAG_CLIPBOARD -> R.styleable.Keyboard_iconClipboardNormalKey
TAG_SELECT_ALL -> R.styleable.Keyboard_iconSelectAll
TAG_COPY -> R.styleable.Keyboard_iconCopyKey
TAG_ONE_HANDED -> R.styleable.Keyboard_iconStartOneHandedMode
TAG_LEFT -> R.styleable.Keyboard_iconArrowLeft
TAG_RIGHT -> R.styleable.Keyboard_iconArrowRight
TAG_UP -> R.styleable.Keyboard_iconArrowUp
TAG_DOWN -> R.styleable.Keyboard_iconArrowDown
TAG_UNDO -> R.styleable.Keyboard_iconUndo
TAG_REDO -> R.styleable.Keyboard_iconRedo
TAG_CLEAR_CLIPBOARD -> R.styleable.Keyboard_iconClearClipboardKey
else -> throw IllegalArgumentException("no styleable id for $tag")
}
const val TAG_VOICE = "voice_key"
const val TAG_CLIPBOARD = "clipboard_key"
const val TAG_CLEAR_CLIPBOARD = "clear_clipboard"
const val TAG_SETTINGS = "settings_key"
const val TAG_SELECT_ALL = "select_all_key"
const val TAG_COPY = "copy_key"
const val TAG_ONE_HANDED = "one_handed_key"
const val TAG_LEFT = "left_key"
const val TAG_RIGHT = "right_key"
const val TAG_UP = "up_key"
const val TAG_DOWN = "down_key"
const val TAG_REDO = "undo"
const val TAG_UNDO = "redo"