Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;

Expand Down Expand Up @@ -157,6 +157,8 @@ private void showPopupKeysPanelInternal(final View parentView, final Controller

mOriginX = x + container.getPaddingLeft();
mOriginY = y + container.getPaddingTop();
var center = panelX + getMeasuredWidth() / 2;
controller.setLayoutGravity(center < pointX? Gravity.RIGHT : center > pointX? Gravity.LEFT : Gravity.NO_GRAVITY);
controller.onShowPopupKeysPanel(this);
final PopupKeysKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
if (accessibilityDelegate != null
Expand Down Expand Up @@ -314,28 +316,4 @@ public boolean onHoverEvent(final MotionEvent event) {
}
return super.onHoverEvent(event);
}

private View getContainerView() {
return (View)getParent();
}

@Override
public void showInParent(final ViewGroup parentView) {
removeFromParent();
parentView.addView(getContainerView());
}

@Override
public void removeFromParent() {
final View containerView = getContainerView();
final ViewGroup currentParent = (ViewGroup)containerView.getParent();
if (currentParent != null) {
currentParent.removeView(containerView);
}
}

@Override
public boolean isShowingInParent() {
return (getContainerView().getParent() != null);
}
}
28 changes: 25 additions & 3 deletions app/src/main/java/helium314/keyboard/keyboard/PopupKeysPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

public interface PopupKeysPanel {
interface Controller {
/**
* Set the layout gravity.
* @param layoutGravity requested by the popup
*/
default void setLayoutGravity(int layoutGravity) {
}

/**
* Add the {@link PopupKeysPanel} to the target view.
* @param panel the panel to be shown.
Expand Down Expand Up @@ -127,20 +134,35 @@ void showPopupKeysPanel(View parentView, Controller controller, int pointX,
*/
int translateY(int y);

default View getContainerView() {
return (View) ((View) this).getParent();
}

/**
* Show this {@link PopupKeysPanel} in the parent view.
*
* @param parentView the {@link ViewGroup} that hosts this {@link PopupKeysPanel}.
*/
void showInParent(ViewGroup parentView);
default void showInParent(ViewGroup parentView) {
removeFromParent();
parentView.addView(getContainerView());
}

/**
* Remove this {@link PopupKeysPanel} from the parent view.
*/
void removeFromParent();
default void removeFromParent() {
final View containerView = getContainerView();
final ViewGroup currentParent = (ViewGroup)containerView.getParent();
if (currentParent != null) {
currentParent.removeView(containerView);
}
}

/**
* Return whether the panel is currently being shown.
*/
boolean isShowingInParent();
default boolean isShowingInParent() {
return getContainerView().getParent() != null;
}
}
121 changes: 121 additions & 0 deletions app/src/main/java/helium314/keyboard/keyboard/PopupTextView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (C) 2011 The Android Open Source Project
* modified
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
*/

package helium314.keyboard.keyboard;

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import helium314.keyboard.keyboard.emoji.OnKeyEventListener;
import helium314.keyboard.keyboard.internal.KeyDrawParams;
import helium314.keyboard.latin.R;
import helium314.keyboard.latin.common.ColorType;
import helium314.keyboard.latin.common.CoordinateUtils;
import helium314.keyboard.latin.settings.Settings;


/**
* A view that displays popup text.
*/
public class PopupTextView extends TextView implements PopupKeysPanel {
private final int[] mCoordinates = CoordinateUtils.newInstance();
private final Typeface mTypeface;
private Controller mController = EMPTY_CONTROLLER;
private int mOriginX;
private int mOriginY;
private Key mKey;
private OnKeyEventListener mListener;

public PopupTextView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.popupKeysKeyboardViewStyle);
}

public PopupTextView(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
mTypeface = Settings.getInstance().getCustomTypeface();
}

public void setKeyDrawParams(Key key, KeyDrawParams drawParams) {
mKey = key;
Settings.getValues().mColors.setBackground(this, ColorType.KEY_PREVIEW_BACKGROUND);
setTextColor(drawParams.mPreviewTextColor);
setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectHintTextSize(drawParams) << 1);
setTypeface(mTypeface == null ? key.selectTypeface(drawParams) : mTypeface);
}

@Override
public void showPopupKeysPanel(final View parentView, final Controller controller,
final int pointX, final int pointY, final KeyboardActionListener listener) {
showPopupKeysPanelInternal(parentView, controller, pointX, pointY);
}

@Override
public void showPopupKeysPanel(final View parentView, final Controller controller,
final int pointX, final int pointY, final OnKeyEventListener listener) {
mListener = listener;
showPopupKeysPanelInternal(parentView, controller, pointX, pointY);
}

private void showPopupKeysPanelInternal(final View parentView, final Controller controller,
final int pointX, final int pointY) {
mController = controller;
final View container = getContainerView();
// The coordinates of panel's left-top corner in parentView's coordinate system.
// We need to consider background drawable paddings.
final int x = pointX - getMeasuredWidth() / 2 - container.getPaddingLeft() - getPaddingLeft();
final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom()
+ getPaddingBottom();

parentView.getLocationInWindow(mCoordinates);
// Ensure the horizontal position of the panel does not extend past the parentView edges.
final int maxX = parentView.getMeasuredWidth() - container.getMeasuredWidth();
final int panelX = Math.max(0, Math.min(maxX, x)) + CoordinateUtils.x(mCoordinates);
final int panelY = y + CoordinateUtils.y(mCoordinates);
container.setX(panelX);
container.setY(panelY);

mOriginX = x + container.getPaddingLeft();
mOriginY = y + container.getPaddingTop();
controller.setLayoutGravity(Gravity.NO_GRAVITY);
controller.onShowPopupKeysPanel(this);
}

@Override
public void onDownEvent(final int x, final int y, final int pointerId, final long eventTime) {
}

@Override
public void onMoveEvent(final int x, final int y, final int pointerId, final long eventTime) {
}

@Override
public void onUpEvent(final int x, final int y, final int pointerId, final long eventTime) {
mListener.onReleaseKey(mKey);
}

@Override
public void dismissPopupKeysPanel() {
if (!isShowingInParent()) {
return;
}
mController.onDismissPopupKeysPanel();
}

@Override
public int translateX(final int x) {
return x - mOriginX;
}

@Override
public int translateY(final int y) {
return y - mOriginY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
import android.graphics.PorterDuffXfermode;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.LinearLayout;
import helium314.keyboard.keyboard.PopupTextView;
import helium314.keyboard.latin.RichInputMethodManager;
import helium314.keyboard.latin.SingleDictionaryFacilitator;
import helium314.keyboard.latin.SuggestedWords;
import helium314.keyboard.latin.utils.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
Expand All @@ -39,6 +45,7 @@
import helium314.keyboard.latin.R;
import helium314.keyboard.latin.common.CoordinateUtils;
import helium314.keyboard.latin.settings.Settings;
import helium314.keyboard.latin.utils.ScriptUtils;

import java.util.WeakHashMap;

Expand Down Expand Up @@ -74,12 +81,16 @@ public void onReleaseKey(final Key key) {}

// More keys keyboard
private final View mPopupKeysKeyboardContainer;
private final PopupTextView mDescriptionView;
private final PopupKeysKeyboardView mPopupKeysKeyboardView;
private final WeakHashMap<Key, Keyboard> mPopupKeysKeyboardCache = new WeakHashMap<>();
private final boolean mConfigShowPopupKeysKeyboardAtTouchedPoint;
private final ViewGroup mPopupKeysPlacerView;
// More keys panel (used by popup keys keyboard view)
// TODO: Consider extending to support multiple popup keys panels
private PopupKeysPanel mPopupKeysPanel;
private SingleDictionaryFacilitator mDictionaryFacilitator;
private final int mDefaultLayoutGravity;

public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle);
Expand All @@ -102,6 +113,10 @@ public EmojiPageKeyboardView(final Context context, final AttributeSet attrs,

final LayoutInflater inflater = LayoutInflater.from(getContext());
mPopupKeysKeyboardContainer = inflater.inflate(popupKeysKeyboardLayoutId, null);
mDescriptionView = mPopupKeysKeyboardContainer.findViewById(R.id.description_view);
mPopupKeysKeyboardView = mPopupKeysKeyboardContainer.findViewById(R.id.popup_keys_keyboard_view);
var locale = RichInputMethodManager.getInstance().getCurrentSubtype().getLocale();
mDefaultLayoutGravity = ScriptUtils.isScriptRtl(ScriptUtils.script(locale))? Gravity.RIGHT : Gravity.LEFT;
}

@Override
Expand Down Expand Up @@ -150,6 +165,10 @@ public void setOnKeyEventListener(final OnKeyEventListener listener) {
mListener = listener;
}

void setDictionaryFacilitator(SingleDictionaryFacilitator dictionaryFacilitator) {
mDictionaryFacilitator = dictionaryFacilitator;
}

/**
* {@inheritDoc}
*/
Expand All @@ -169,7 +188,8 @@ public void setKeyboard(@NonNull final Keyboard keyboard) {
}

@Nullable
public PopupKeysPanel showPopupKeysKeyboard(@NonNull final Key key, final int lastX, final int lastY) {
private PopupKeysPanel showPopupKeysKeyboard(@NonNull final Key key) {
mPopupKeysKeyboardView.setVisibility(GONE);
final PopupKeySpec[] popupKeys = key.getPopupKeys();
if (popupKeys == null) {
return null;
Expand All @@ -182,21 +202,9 @@ public PopupKeysPanel showPopupKeysKeyboard(@NonNull final Key key, final int la
mPopupKeysKeyboardCache.put(key, popupKeysKeyboard);
}

final View container = mPopupKeysKeyboardContainer;
final PopupKeysKeyboardView popupKeysKeyboardView = container.findViewById(R.id.popup_keys_keyboard_view);
popupKeysKeyboardView.setKeyboard(popupKeysKeyboard);
container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

final int[] lastCoords = CoordinateUtils.newCoordinateArray(1, lastX, lastY);
// The popup keys keyboard is usually horizontally aligned with the center of the parent key.
// If showPopupKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
// keys keyboard is placed at the touch point of the parent key.
final int pointX = mConfigShowPopupKeysKeyboardAtTouchedPoint
? CoordinateUtils.x(lastCoords)
: key.getX() + key.getWidth() / 2;
final int pointY = key.getY();
popupKeysKeyboardView.showPopupKeysPanel(this, this, pointX, pointY, mListener);
return popupKeysKeyboardView;
mPopupKeysKeyboardView.setKeyboard(popupKeysKeyboard);
mPopupKeysKeyboardView.setVisibility(VISIBLE);
return mPopupKeysKeyboardView;
}

private void dismissPopupKeysPanel() {
Expand All @@ -209,6 +217,16 @@ public boolean isShowingPopupKeysPanel() {
return mPopupKeysPanel != null;
}

@Override
public void setLayoutGravity(int layoutGravity) {
var layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = layoutGravity != Gravity.NO_GRAVITY? layoutGravity : mDefaultLayoutGravity;
mPopupKeysKeyboardContainer.setLayoutParams(layoutParams);
mDescriptionView.setLayoutParams(layoutParams);
mPopupKeysKeyboardView.setLayoutParams(layoutParams);
}

@Override
public void onShowPopupKeysPanel(final PopupKeysPanel panel) {
// install placer view only when needed instead of when this
Expand Down Expand Up @@ -290,9 +308,11 @@ private void onLongPressed(final Key key) {
return;
}

var descriptionPanel = showDescription(key);
final PopupKeysPanel popupKeysPanel = showPopupKeysKeyboard(key);

final int x = mLastX;
final int y = mLastY;
final PopupKeysPanel popupKeysPanel = showPopupKeysKeyboard(key, x, y);
if (popupKeysPanel != null) {
final int translatedX = popupKeysPanel.translateX(x);
final int translatedY = popupKeysPanel.translateY(y);
Expand All @@ -301,6 +321,38 @@ private void onLongPressed(final Key key) {
// want any scroll to append during this entire input.
disallowParentInterceptTouchEvent(true);
}

if (popupKeysPanel != null || descriptionPanel != null) {
mPopupKeysKeyboardContainer.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

final int[] lastCoords = CoordinateUtils.newCoordinateArray(1, x, y);
// The popup keys keyboard is usually horizontally aligned with the center of the parent key.
// If showPopupKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
// keys keyboard is placed at the touch point of the parent key.
final int pointX = mConfigShowPopupKeysKeyboardAtTouchedPoint
? CoordinateUtils.x(lastCoords)
: key.getX() + key.getWidth() / 2;
final int pointY = key.getY() - getKeyboard().mVerticalGap;
(popupKeysPanel != null? popupKeysPanel : descriptionPanel)
.showPopupKeysPanel(this, this, pointX, pointY, mListener);
}
}

private PopupKeysPanel showDescription(Key key) {
mDescriptionView.setVisibility(GONE);
if (mDictionaryFacilitator == null) {
return null;
}

var wordProperty = mDictionaryFacilitator.getWordProperty(key.getLabel());
if (! wordProperty.mHasShortcuts) {
return null;
}

mDescriptionView.setText(wordProperty.mShortcutTargets.get(0).mWord);
mDescriptionView.setKeyDrawParams(key, getKeyDrawParams());
mDescriptionView.setVisibility(VISIBLE);
return mDescriptionView;
}

private void registerPress(final Key key) {
Expand Down
Loading
Loading