mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-17 15:32:48 +00:00
Allow splitting all layouts instead of having to define split layouts in xml (#258)
This commit is contained in:
parent
778f160c07
commit
1c0fb0c672
11 changed files with 442 additions and 290 deletions
|
@ -282,18 +282,24 @@ public class Key implements Comparable<Key> {
|
||||||
mEnabled = keyParams.mEnabled;
|
mEnabled = keyParams.mEnabled;
|
||||||
|
|
||||||
// stuff to create
|
// stuff to create
|
||||||
mWidth = keyParams.mWidth;
|
// interestingly it looks a little better when rounding horizontalGap to int immediately instead of using horizontalGapFloat
|
||||||
mHeight = keyParams.mHeight;
|
// but using float for determining mX and mWidth is more correct and keyboard ends up looking exactly like before introduction of KeyParams
|
||||||
|
final float horizontalGapFloat = isSpacer() ? 0 : keyParams.mKeyboardParams.mHorizontalGap;
|
||||||
|
mHorizontalGap = Math.round(horizontalGapFloat);
|
||||||
|
mVerticalGap = Math.round(keyParams.mKeyboardParams.mVerticalGap);
|
||||||
|
mWidth = Math.round(keyParams.mFullWidth - horizontalGapFloat);
|
||||||
|
// todo (later): height better should be rounded, but this may end up shifting all keys up by one pixel,
|
||||||
|
// increasing the keyboard height by one pixel, but not for emoji keyboard -> the 1 pixel shift feels very wrong
|
||||||
|
// how to do it properly? check again when keyboard height is same for all views!
|
||||||
|
mHeight = (int) (keyParams.mFullHeight - keyParams.mKeyboardParams.mVerticalGap);
|
||||||
if (!isSpacer() && (mWidth == 0 || mHeight == 0)) {
|
if (!isSpacer() && (mWidth == 0 || mHeight == 0)) {
|
||||||
throw new IllegalStateException("key needs positive width and height");
|
throw new IllegalStateException("key needs positive width and height");
|
||||||
}
|
}
|
||||||
mHorizontalGap = isSpacer() ? 0 : keyParams.mHorizontalGap;
|
|
||||||
mVerticalGap = keyParams.mVerticalGap;
|
|
||||||
// Horizontal gap is divided equally to both sides of the key.
|
// Horizontal gap is divided equally to both sides of the key.
|
||||||
mX = Math.round(keyParams.xPos + ((float) keyParams.mHorizontalGap) / 2);
|
mX = Math.round(keyParams.xPos + horizontalGapFloat / 2);
|
||||||
mY = keyParams.yPos;
|
mY = Math.round(keyParams.yPos);
|
||||||
mHitBox.set(Math.round(keyParams.xPos), keyParams.yPos, Math.round(keyParams.xPos + mWidth + mHorizontalGap) + 1,
|
mHitBox.set(Math.round(keyParams.xPos), (int) keyParams.yPos, Math.round(keyParams.xPos + keyParams.mFullWidth) + 1,
|
||||||
keyParams.yPos + mHeight + mHorizontalGap);
|
Math.round(keyParams.yPos + keyParams.mFullHeight));
|
||||||
mHashCode = computeHashCode(this);
|
mHashCode = computeHashCode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,32 +943,30 @@ public class Key implements Comparable<Key> {
|
||||||
// for creating keys that might get modified later
|
// for creating keys that might get modified later
|
||||||
public static class KeyParams {
|
public static class KeyParams {
|
||||||
// params for building
|
// params for building
|
||||||
boolean isSpacer;
|
private boolean isSpacer;
|
||||||
private final KeyboardParams mParams; // for reading gaps and keyboard width / height
|
private final KeyboardParams mKeyboardParams; // for reading gaps and keyboard width / height
|
||||||
public float mRelativeWidth; // also allows -1f as value, this means "fill right"
|
public float mRelativeWidth;
|
||||||
public float mRelativeHeight; // also allows negative values, indicating absolute height is defined
|
public float mRelativeHeight; // also should allow negative values, indicating absolute height is defined
|
||||||
|
|
||||||
// stuff that likely remains after constructor, maybe make final
|
// params that may change
|
||||||
final int mCode;
|
public float mFullWidth;
|
||||||
|
public float mFullHeight;
|
||||||
|
public float xPos;
|
||||||
|
public float yPos;
|
||||||
|
|
||||||
|
// params that remains constant
|
||||||
|
public final int mCode;
|
||||||
@Nullable final String mLabel;
|
@Nullable final String mLabel;
|
||||||
@Nullable final String mHintLabel;
|
@Nullable final String mHintLabel;
|
||||||
final int mLabelFlags;
|
final int mLabelFlags;
|
||||||
final int mIconId;
|
final int mIconId;
|
||||||
public final MoreKeySpec[] mMoreKeys;
|
public final MoreKeySpec[] mMoreKeys;
|
||||||
final int mMoreKeysColumnAndFlags;
|
final int mMoreKeysColumnAndFlags;
|
||||||
final int mBackgroundType;
|
public final int mBackgroundType;
|
||||||
final int mActionFlags;
|
final int mActionFlags;
|
||||||
@Nullable final KeyVisualAttributes mKeyVisualAttributes;
|
@Nullable final KeyVisualAttributes mKeyVisualAttributes;
|
||||||
@Nullable final OptionalAttributes mOptionalAttributes;
|
@Nullable final OptionalAttributes mOptionalAttributes;
|
||||||
public boolean mEnabled = true;
|
public final boolean mEnabled;
|
||||||
|
|
||||||
// stuff that may very well change
|
|
||||||
private int mWidth;
|
|
||||||
private int mHeight;
|
|
||||||
private int mHorizontalGap;
|
|
||||||
private int mVerticalGap;
|
|
||||||
private float xPos;
|
|
||||||
private int yPos;
|
|
||||||
|
|
||||||
public static KeyParams newSpacer(final TypedArray keyAttr, final KeyStyle keyStyle,
|
public static KeyParams newSpacer(final TypedArray keyAttr, final KeyStyle keyStyle,
|
||||||
final KeyboardParams params, final XmlKeyboardRow row) {
|
final KeyboardParams params, final XmlKeyboardRow row) {
|
||||||
|
@ -971,36 +975,25 @@ public class Key implements Comparable<Key> {
|
||||||
return keyParams;
|
return keyParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static KeyParams newSpacer(final KeyboardParams params) {
|
||||||
|
return new KeyParams(params);
|
||||||
|
}
|
||||||
|
|
||||||
public Key createKey() {
|
public Key createKey() {
|
||||||
if (isSpacer) return new Spacer(this);
|
if (isSpacer) return new Spacer(this);
|
||||||
return new Key(this);
|
return new Key(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: use it
|
public void setDimensionsFromRelativeSize(final float newX, final float newY) {
|
||||||
// first for inserting spacers to get a split keyboard
|
|
||||||
// any use for adjusting width or height?
|
|
||||||
// width is already more or less done with one-handed mode, but this could be more flexible
|
|
||||||
// height is already implemented via the setting
|
|
||||||
// any use in combination with number row?
|
|
||||||
// when completely replacing number row stuff, also moreKeys stuff would need to be adjusted
|
|
||||||
public void setDimensionsFromRelativeSize(final int newX, final int newY) {
|
|
||||||
if (mRelativeHeight == 0 || mRelativeWidth == 0)
|
if (mRelativeHeight == 0 || mRelativeWidth == 0)
|
||||||
throw new IllegalStateException("can't use setUsingRelativeHeight, not all fields are set");
|
throw new IllegalStateException("can't use setUsingRelativeHeight, not all fields are set");
|
||||||
if (mRelativeHeight < 0)
|
if (mRelativeHeight < 0)
|
||||||
throw new IllegalStateException("can't (yet) deal with absolute height"); // todo: decide... maybe just use it and deal with it properly when it needs to be adjusted?
|
// todo (later): deal with it properly when it needs to be adjusted, i.e. when changing moreKeys or moreSuggestions
|
||||||
|
throw new IllegalStateException("can't (yet) deal with absolute height");
|
||||||
xPos = newX;
|
xPos = newX;
|
||||||
yPos = newY;
|
yPos = newY;
|
||||||
float horizontalGap = isSpacer ? 0f : mParams.mRelativeHorizontalGap * mParams.mId.mWidth; // gap width / height is based on params.mId.height / width
|
mFullWidth = mRelativeWidth * mKeyboardParams.mBaseWidth;
|
||||||
float verticalGap = mParams.mRelativeVerticalGap * mParams.mId.mHeight;
|
mFullHeight = mRelativeHeight * mKeyboardParams.mBaseHeight;
|
||||||
mHorizontalGap = (int) horizontalGap;
|
|
||||||
mVerticalGap = (int) verticalGap;
|
|
||||||
float keyWidth;
|
|
||||||
if (mRelativeWidth > 0)
|
|
||||||
keyWidth = mRelativeWidth * mParams.mBaseWidth; // key width / height is based on params.mBaseHeight / width
|
|
||||||
else // fillRight
|
|
||||||
keyWidth = (mParams.mOccupiedWidth - mParams.mRightPadding) - xPos; // right keyboard edge - x
|
|
||||||
mWidth = Math.round(keyWidth - horizontalGap);
|
|
||||||
mHeight = (int) (mRelativeHeight * mParams.mBaseHeight - verticalGap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1017,26 +1010,23 @@ public class Key implements Comparable<Key> {
|
||||||
public KeyParams(@Nullable final String keySpec, @NonNull final TypedArray keyAttr,
|
public KeyParams(@Nullable final String keySpec, @NonNull final TypedArray keyAttr,
|
||||||
@NonNull final KeyStyle style, @NonNull final KeyboardParams params,
|
@NonNull final KeyStyle style, @NonNull final KeyboardParams params,
|
||||||
@NonNull final XmlKeyboardRow row) {
|
@NonNull final XmlKeyboardRow row) {
|
||||||
mParams = params;
|
mKeyboardParams = params;
|
||||||
mRelativeHeight = row.mRelativeRowHeight;
|
mRelativeHeight = row.mRelativeRowHeight;
|
||||||
mRelativeWidth = row.getRelativeKeyWidth(keyAttr);
|
mRelativeWidth = row.getRelativeKeyWidth(keyAttr);
|
||||||
mHorizontalGap = params.mHorizontalGap;
|
|
||||||
mVerticalGap = params.mVerticalGap;
|
|
||||||
|
|
||||||
final float horizontalGapFloat = mHorizontalGap;
|
|
||||||
final int rowHeight = row.getRowHeight();
|
|
||||||
mHeight = rowHeight - mVerticalGap;
|
|
||||||
|
|
||||||
|
mFullHeight = row.getRowHeight();
|
||||||
xPos = row.getKeyX(keyAttr);
|
xPos = row.getKeyX(keyAttr);
|
||||||
final float keyWidth = row.getKeyWidth(keyAttr, xPos);
|
mFullWidth = row.getKeyWidth(keyAttr, xPos);
|
||||||
|
if (mRelativeWidth == -1f) {
|
||||||
|
// determine from actual width if using fillRight
|
||||||
|
mRelativeWidth = mFullWidth / mKeyboardParams.mBaseWidth;
|
||||||
|
}
|
||||||
yPos = row.getKeyY();
|
yPos = row.getKeyY();
|
||||||
|
|
||||||
mWidth = Math.round(keyWidth - horizontalGapFloat);
|
|
||||||
// Update row to have current x coordinate.
|
// Update row to have current x coordinate.
|
||||||
row.setXPos(xPos + keyWidth);
|
row.setXPos(xPos + mFullWidth);
|
||||||
|
|
||||||
mBackgroundType = style.getInt(keyAttr,
|
mBackgroundType = style.getInt(keyAttr, R.styleable.Keyboard_Key_backgroundType, row.getDefaultBackgroundType());
|
||||||
R.styleable.Keyboard_Key_backgroundType, row.getDefaultBackgroundType());
|
|
||||||
|
|
||||||
final int baseWidth = params.mBaseWidth;
|
final int baseWidth = params.mBaseWidth;
|
||||||
final int visualInsetsLeft = Math.round(keyAttr.getFraction(
|
final int visualInsetsLeft = Math.round(keyAttr.getFraction(
|
||||||
|
@ -1058,13 +1048,11 @@ public class Key implements Comparable<Key> {
|
||||||
int value;
|
int value;
|
||||||
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
|
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
|
||||||
// Override with fixed column order number and set a relevant mode value.
|
// Override with fixed column order number and set a relevant mode value.
|
||||||
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_AUTO_ORDER
|
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_AUTO_ORDER | (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
||||||
| (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
|
||||||
}
|
}
|
||||||
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
|
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
|
||||||
// Override with fixed column order number and set a relevant mode value.
|
// Override with fixed column order number and set a relevant mode value.
|
||||||
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER
|
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER | (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
||||||
| (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
|
||||||
}
|
}
|
||||||
if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
|
if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
|
||||||
moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_HAS_LABELS;
|
moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_HAS_LABELS;
|
||||||
|
@ -1081,8 +1069,7 @@ public class Key implements Comparable<Key> {
|
||||||
if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) {
|
if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) {
|
||||||
additionalMoreKeys = null;
|
additionalMoreKeys = null;
|
||||||
} else {
|
} else {
|
||||||
additionalMoreKeys = style.getStringArray(keyAttr,
|
additionalMoreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
|
||||||
R.styleable.Keyboard_Key_additionalMoreKeys);
|
|
||||||
}
|
}
|
||||||
moreKeys = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
|
moreKeys = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
|
||||||
if (moreKeys != null) {
|
if (moreKeys != null) {
|
||||||
|
@ -1117,8 +1104,7 @@ public class Key implements Comparable<Key> {
|
||||||
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
|
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
|
||||||
mHintLabel = null;
|
mHintLabel = null;
|
||||||
} else {
|
} else {
|
||||||
final String hintLabel = style.getString(
|
final String hintLabel = style.getString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
|
||||||
keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
|
|
||||||
mHintLabel = needsToUpcase
|
mHintLabel = needsToUpcase
|
||||||
? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing)
|
? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing)
|
||||||
: hintLabel;
|
: hintLabel;
|
||||||
|
@ -1128,12 +1114,12 @@ public class Key implements Comparable<Key> {
|
||||||
outputText = StringUtils.toTitleCaseOfKeyLabel(outputText, localeForUpcasing);
|
outputText = StringUtils.toTitleCaseOfKeyLabel(outputText, localeForUpcasing);
|
||||||
}
|
}
|
||||||
// Choose the first letter of the label as primary code if not specified.
|
// Choose the first letter of the label as primary code if not specified.
|
||||||
if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
|
if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) && !TextUtils.isEmpty(mLabel)) {
|
||||||
&& !TextUtils.isEmpty(mLabel)) {
|
|
||||||
if (StringUtils.codePointCount(mLabel) == 1) {
|
if (StringUtils.codePointCount(mLabel) == 1) {
|
||||||
// Use the first letter of the hint label if shiftedLetterActivated flag is
|
// Use the first letter of the hint label if shiftedLetterActivated flag is
|
||||||
// specified.
|
// specified.
|
||||||
if ((mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0 && (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0 && !TextUtils.isEmpty(mHintLabel)) {
|
if ((mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0 && (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0
|
||||||
|
&& !TextUtils.isEmpty(mHintLabel)) {
|
||||||
mCode = mHintLabel.codePointAt(0);
|
mCode = mHintLabel.codePointAt(0);
|
||||||
} else {
|
} else {
|
||||||
mCode = mLabel.codePointAt(0);
|
mCode = mLabel.codePointAt(0);
|
||||||
|
@ -1152,8 +1138,7 @@ public class Key implements Comparable<Key> {
|
||||||
mCode = CODE_OUTPUT_TEXT;
|
mCode = CODE_OUTPUT_TEXT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mCode = needsToUpcase ? StringUtils.toTitleCaseOfKeyCode(code, localeForUpcasing)
|
mCode = needsToUpcase ? StringUtils.toTitleCaseOfKeyCode(code, localeForUpcasing) : code;
|
||||||
: code;
|
|
||||||
}
|
}
|
||||||
final int altCodeInAttr = KeySpecParser.parseCode(
|
final int altCodeInAttr = KeySpecParser.parseCode(
|
||||||
style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED);
|
style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED);
|
||||||
|
@ -1163,6 +1148,7 @@ public class Key implements Comparable<Key> {
|
||||||
mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode,
|
mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode,
|
||||||
disabledIconId, visualInsetsLeft, visualInsetsRight);
|
disabledIconId, visualInsetsLeft, visualInsetsRight);
|
||||||
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
|
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
|
||||||
|
mEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** for <GridRows/> */
|
/** for <GridRows/> */
|
||||||
|
@ -1170,11 +1156,9 @@ public class Key implements Comparable<Key> {
|
||||||
@Nullable final String hintLabel, @Nullable final String moreKeySpecs,
|
@Nullable final String hintLabel, @Nullable final String moreKeySpecs,
|
||||||
final int labelFlags, final int backgroundType, final int x, final int y,
|
final int labelFlags, final int backgroundType, final int x, final int y,
|
||||||
final int width, final int height, final KeyboardParams params) {
|
final int width, final int height, final KeyboardParams params) {
|
||||||
mParams = params;
|
mKeyboardParams = params;
|
||||||
mWidth = width - params.mHorizontalGap;
|
mFullWidth = width;
|
||||||
mHeight = height - params.mVerticalGap;
|
mFullHeight = height;
|
||||||
mHorizontalGap = params.mHorizontalGap;
|
|
||||||
mVerticalGap = params.mVerticalGap;
|
|
||||||
mHintLabel = hintLabel;
|
mHintLabel = hintLabel;
|
||||||
mLabelFlags = labelFlags;
|
mLabelFlags = labelFlags;
|
||||||
mBackgroundType = backgroundType;
|
mBackgroundType = backgroundType;
|
||||||
|
@ -1184,8 +1168,7 @@ public class Key implements Comparable<Key> {
|
||||||
if (moreKeySpecs != null) {
|
if (moreKeySpecs != null) {
|
||||||
String[] moreKeys = MoreKeySpec.splitKeySpecs(moreKeySpecs);
|
String[] moreKeys = MoreKeySpec.splitKeySpecs(moreKeySpecs);
|
||||||
// Get maximum column order number and set a relevant mode value.
|
// Get maximum column order number and set a relevant mode value.
|
||||||
int moreKeysColumnAndFlags = MORE_KEYS_MODE_MAX_COLUMN_WITH_AUTO_ORDER
|
int moreKeysColumnAndFlags = MORE_KEYS_MODE_MAX_COLUMN_WITH_AUTO_ORDER | params.mMaxMoreKeysKeyboardColumn;
|
||||||
| params.mMaxMoreKeysKeyboardColumn;
|
|
||||||
int value;
|
int value;
|
||||||
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
|
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
|
||||||
// Override with fixed column order number and set a relevant mode value.
|
// Override with fixed column order number and set a relevant mode value.
|
||||||
|
@ -1194,8 +1177,7 @@ public class Key implements Comparable<Key> {
|
||||||
}
|
}
|
||||||
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
|
if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
|
||||||
// Override with fixed column order number and set a relevant mode value.
|
// Override with fixed column order number and set a relevant mode value.
|
||||||
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER
|
moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER | (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
||||||
| (value & MORE_KEYS_COLUMN_NUMBER_MASK);
|
|
||||||
}
|
}
|
||||||
if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
|
if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
|
||||||
moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_HAS_LABELS;
|
moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_HAS_LABELS;
|
||||||
|
@ -1235,5 +1217,48 @@ public class Key implements Comparable<Key> {
|
||||||
mIconId = KeyboardIconsSet.ICON_UNDEFINED;
|
mIconId = KeyboardIconsSet.ICON_UNDEFINED;
|
||||||
mKeyVisualAttributes = null;
|
mKeyVisualAttributes = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** constructor for a spacer whose size MUST be determined using setDimensionsFromRelativeSize */
|
||||||
|
private KeyParams(final KeyboardParams params) {
|
||||||
|
isSpacer = true; // this is only for spacer!
|
||||||
|
mKeyboardParams = params;
|
||||||
|
|
||||||
|
mCode = CODE_UNSPECIFIED;
|
||||||
|
mLabel = null;
|
||||||
|
mHintLabel = null;
|
||||||
|
mKeyVisualAttributes = null;
|
||||||
|
mOptionalAttributes = null;
|
||||||
|
mIconId = KeyboardIconsSet.ICON_UNDEFINED;
|
||||||
|
mBackgroundType = BACKGROUND_TYPE_NORMAL;
|
||||||
|
mActionFlags = ACTION_FLAGS_NO_KEY_PREVIEW;
|
||||||
|
mMoreKeys = null;
|
||||||
|
mMoreKeysColumnAndFlags = 0;
|
||||||
|
mLabelFlags = LABEL_FLAGS_FONT_NORMAL;
|
||||||
|
mEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyParams(final KeyParams keyParams) {
|
||||||
|
xPos = keyParams.xPos;
|
||||||
|
yPos = keyParams.yPos;
|
||||||
|
mRelativeWidth = keyParams.mRelativeWidth;
|
||||||
|
mRelativeHeight = keyParams.mRelativeHeight;
|
||||||
|
isSpacer = keyParams.isSpacer;
|
||||||
|
mKeyboardParams = keyParams.mKeyboardParams;
|
||||||
|
mEnabled = keyParams.mEnabled;
|
||||||
|
|
||||||
|
mCode = keyParams.mCode;
|
||||||
|
mLabel = keyParams.mLabel;
|
||||||
|
mHintLabel = keyParams.mHintLabel;
|
||||||
|
mLabelFlags = keyParams.mLabelFlags;
|
||||||
|
mIconId = keyParams.mIconId;
|
||||||
|
mFullWidth = keyParams.mFullWidth;
|
||||||
|
mFullHeight = keyParams.mFullHeight;
|
||||||
|
mMoreKeys = keyParams.mMoreKeys;
|
||||||
|
mMoreKeysColumnAndFlags = keyParams.mMoreKeysColumnAndFlags;
|
||||||
|
mBackgroundType = keyParams.mBackgroundType;
|
||||||
|
mActionFlags = keyParams.mActionFlags;
|
||||||
|
mKeyVisualAttributes = keyParams.mKeyVisualAttributes;
|
||||||
|
mOptionalAttributes = keyParams.mOptionalAttributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,8 +457,7 @@ public final class KeyboardLayoutSet {
|
||||||
elementParams.mProximityCharsCorrectionEnabled = a.getBoolean(
|
elementParams.mProximityCharsCorrectionEnabled = a.getBoolean(
|
||||||
R.styleable.KeyboardLayoutSet_Element_enableProximityCharsCorrection,
|
R.styleable.KeyboardLayoutSet_Element_enableProximityCharsCorrection,
|
||||||
false);
|
false);
|
||||||
elementParams.mSupportsSplitLayout = a.getBoolean(
|
elementParams.mSupportsSplitLayout = false; // this is to avoid xml parser reading split layouts, todo (later): remove mSupportsSplitLayout
|
||||||
R.styleable.KeyboardLayoutSet_Element_supportsSplitLayout, false);
|
|
||||||
elementParams.mAllowRedundantMoreKeys = a.getBoolean(
|
elementParams.mAllowRedundantMoreKeys = a.getBoolean(
|
||||||
R.styleable.KeyboardLayoutSet_Element_allowRedundantMoreKeys, true);
|
R.styleable.KeyboardLayoutSet_Element_allowRedundantMoreKeys, true);
|
||||||
mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams);
|
mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams);
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 The Android Open Source Project
|
|
||||||
* modified
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.keyboard.internal;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
|
||||||
import org.dslul.openboard.inputmethod.keyboard.Key;
|
|
||||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
|
||||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
|
|
||||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.XmlKeyboardParser;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.R;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
// TODO: Write unit tests for this class.
|
|
||||||
public class KeyboardBuilder<KP extends KeyboardParams> {
|
|
||||||
private static final String BUILDER_TAG = "Keyboard.Builder";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
protected final KP mParams;
|
|
||||||
protected final Context mContext;
|
|
||||||
protected final Resources mResources;
|
|
||||||
|
|
||||||
private int mCurrentY = 0;
|
|
||||||
// currently not used, but will be relevant when resizing a row or inserting a new key
|
|
||||||
private float mCurrentX = 0f;
|
|
||||||
private boolean mLeftEdge;
|
|
||||||
private boolean mTopEdge;
|
|
||||||
private Key mRightEdgeKey = null;
|
|
||||||
private ArrayList<ArrayList<Key.KeyParams>> keysInRows;
|
|
||||||
|
|
||||||
public KeyboardBuilder(final Context context, @NonNull final KP params) {
|
|
||||||
mContext = context;
|
|
||||||
final Resources res = context.getResources();
|
|
||||||
mResources = res;
|
|
||||||
|
|
||||||
mParams = params;
|
|
||||||
|
|
||||||
params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
|
|
||||||
params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAllowRedundantMoreKeys(final boolean enabled) {
|
|
||||||
mParams.mAllowRedundantMoreKeys = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyboardBuilder<KP> loadFromXml(final int xmlId, final KeyboardId id) {
|
|
||||||
mParams.mId = id;
|
|
||||||
// loading a keyboard should set default params like mParams.readAttributes(mContext, attrs);
|
|
||||||
// attrs may be null, then default values are used (looks good for "normal" keyboards)
|
|
||||||
try (XmlKeyboardParser keyboardParser = new XmlKeyboardParser(xmlId, mParams, mContext)) {
|
|
||||||
keysInRows = keyboardParser.parseKeyboard();
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
Log.w(BUILDER_TAG, "keyboard XML parse error", e);
|
|
||||||
throw new IllegalArgumentException(e.getMessage(), e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(BUILDER_TAG, "keyboard XML parse error", e);
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@UsedForTesting
|
|
||||||
public void disableTouchPositionCorrectionDataForTest() {
|
|
||||||
mParams.mTouchPositionCorrection.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProximityCharsCorrectionEnabled(final boolean enabled) {
|
|
||||||
mParams.mProximityCharsCorrectionEnabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Keyboard build() {
|
|
||||||
addKeysToParams();
|
|
||||||
return new Keyboard(mParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startKeyboard() {
|
|
||||||
mCurrentY += mParams.mTopPadding;
|
|
||||||
mTopEdge = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRow() {
|
|
||||||
addEdgeSpace(mParams.mLeftPadding);
|
|
||||||
mLeftEdge = true;
|
|
||||||
mRightEdgeKey = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void endRow() {
|
|
||||||
int lastKeyHeight = 0;
|
|
||||||
if (mRightEdgeKey != null) {
|
|
||||||
mRightEdgeKey.markAsRightEdge(mParams);
|
|
||||||
lastKeyHeight = mRightEdgeKey.getHeight() + mRightEdgeKey.getVerticalGap();
|
|
||||||
mRightEdgeKey = null;
|
|
||||||
}
|
|
||||||
addEdgeSpace(mParams.mRightPadding);
|
|
||||||
mCurrentY += lastKeyHeight;
|
|
||||||
mTopEdge = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void endKey(@NonNull final Key key) {
|
|
||||||
mParams.onAddKey(key);
|
|
||||||
if (mLeftEdge) {
|
|
||||||
key.markAsLeftEdge(mParams);
|
|
||||||
mLeftEdge = false;
|
|
||||||
}
|
|
||||||
if (mTopEdge) {
|
|
||||||
key.markAsTopEdge(mParams);
|
|
||||||
}
|
|
||||||
mRightEdgeKey = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void endKeyboard() {
|
|
||||||
mParams.removeRedundantMoreKeys();
|
|
||||||
// {@link #parseGridRows(XmlPullParser,boolean)} may populate keyboard rows higher than
|
|
||||||
// previously expected.
|
|
||||||
final int actualHeight = mCurrentY - mParams.mVerticalGap + mParams.mBottomPadding;
|
|
||||||
mParams.mOccupiedHeight = Math.max(mParams.mOccupiedHeight, actualHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addKeysToParams() {
|
|
||||||
// need to reset it, we need to sum it up to get the height nicely
|
|
||||||
// (though in the end we could just not touch it at all, final used value is the same as the one before resetting)
|
|
||||||
mCurrentY = 0;
|
|
||||||
startKeyboard();
|
|
||||||
for (ArrayList<Key.KeyParams> row : keysInRows) {
|
|
||||||
startRow();
|
|
||||||
for (Key.KeyParams keyParams : row) {
|
|
||||||
endKey(keyParams.createKey());
|
|
||||||
}
|
|
||||||
endRow();
|
|
||||||
}
|
|
||||||
endKeyboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addEdgeSpace(final float width) {
|
|
||||||
mCurrentX += width;
|
|
||||||
mLeftEdge = false;
|
|
||||||
mRightEdgeKey = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
* modified
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
||||||
|
*/
|
||||||
|
package org.dslul.openboard.inputmethod.keyboard.internal
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.util.Log
|
||||||
|
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.Key
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.Keyboard
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.XmlKeyboardParser
|
||||||
|
import org.dslul.openboard.inputmethod.latin.R
|
||||||
|
import org.dslul.openboard.inputmethod.latin.common.Constants
|
||||||
|
import org.dslul.openboard.inputmethod.latin.settings.Settings
|
||||||
|
import org.xmlpull.v1.XmlPullParserException
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
// TODO: Write unit tests for this class.
|
||||||
|
open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context, @JvmField val mParams: KP) {
|
||||||
|
@JvmField
|
||||||
|
protected val mResources: Resources
|
||||||
|
private var mCurrentY = 0
|
||||||
|
|
||||||
|
private var mLeftEdge = false
|
||||||
|
private var mTopEdge = false
|
||||||
|
private var mRightEdgeKey: Key? = null
|
||||||
|
private lateinit var keysInRows: ArrayList<ArrayList<KeyParams>>
|
||||||
|
|
||||||
|
init {
|
||||||
|
val res = mContext.resources
|
||||||
|
mResources = res
|
||||||
|
mParams.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width)
|
||||||
|
mParams.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAllowRedundantMoreKeys(enabled: Boolean) {
|
||||||
|
mParams.mAllowRedundantMoreKeys = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadFromXml(xmlId: Int, id: KeyboardId): KeyboardBuilder<KP> {
|
||||||
|
mParams.mId = id
|
||||||
|
// loading a keyboard should set default params like mParams.readAttributes(mContext, attrs);
|
||||||
|
// attrs may be null, then default values are used (looks good for "normal" keyboards)
|
||||||
|
try {
|
||||||
|
XmlKeyboardParser(xmlId, mParams, mContext).use { keyboardParser ->
|
||||||
|
keysInRows = keyboardParser.parseKeyboard()
|
||||||
|
}
|
||||||
|
} catch (e: XmlPullParserException) {
|
||||||
|
Log.w(BUILDER_TAG, "keyboard XML parse error", e)
|
||||||
|
throw IllegalArgumentException(e.message, e)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.w(BUILDER_TAG, "keyboard XML parse error", e)
|
||||||
|
throw RuntimeException(e.message, e)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
@UsedForTesting
|
||||||
|
fun disableTouchPositionCorrectionDataForTest() {
|
||||||
|
mParams.mTouchPositionCorrection.setEnabled(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setProximityCharsCorrectionEnabled(enabled: Boolean) {
|
||||||
|
mParams.mProximityCharsCorrectionEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun build(): Keyboard {
|
||||||
|
if (Settings.getInstance().current.mIsSplitKeyboardEnabled
|
||||||
|
&& mParams.mId.mElementId in KeyboardId.ELEMENT_ALPHABET..KeyboardId.ELEMENT_SYMBOLS_SHIFTED) {
|
||||||
|
addSplit()
|
||||||
|
}
|
||||||
|
addKeysToParams()
|
||||||
|
return Keyboard(mParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize keyboard using relative params
|
||||||
|
// ideally this should not change anything
|
||||||
|
// but it does a little, depending on how float -> int is done (cast or round, and when to sum up gaps and width)
|
||||||
|
// still should not be more than a pixel difference
|
||||||
|
// keep it around for a while, for testing
|
||||||
|
private fun useRelative() {
|
||||||
|
for (row in keysInRows) {
|
||||||
|
if (row.isEmpty()) continue
|
||||||
|
fillGapsWithSpacers(row)
|
||||||
|
val y = row.first().yPos
|
||||||
|
assert(row.all { it.yPos == y })
|
||||||
|
var currentX = 0f
|
||||||
|
row.forEach {
|
||||||
|
it.setDimensionsFromRelativeSize(currentX, y)
|
||||||
|
currentX += it.mFullWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// necessary for adjusting widths and positions properly
|
||||||
|
// without adding spacers whose width can then be adjusted, we would have to deal with keyXPos,
|
||||||
|
// which is more complicated than expected
|
||||||
|
private fun fillGapsWithSpacers(row: MutableList<KeyParams>) {
|
||||||
|
if (mParams.mId.mElementId !in KeyboardId.ELEMENT_ALPHABET..KeyboardId.ELEMENT_SYMBOLS_SHIFTED) return
|
||||||
|
if (row.isEmpty()) return
|
||||||
|
var currentX = 0f + mParams.mLeftPadding
|
||||||
|
var i = 0
|
||||||
|
while (i < row.size) {
|
||||||
|
val currentKeyXPos = row[i].xPos
|
||||||
|
if (currentKeyXPos > currentX) {
|
||||||
|
// insert spacer
|
||||||
|
val spacer = KeyParams.newSpacer(mParams)
|
||||||
|
spacer.mRelativeWidth = (currentKeyXPos - currentX) / mParams.mBaseWidth
|
||||||
|
spacer.yPos = row[i].yPos
|
||||||
|
spacer.mRelativeHeight = row[i].mRelativeHeight
|
||||||
|
row.add(i, spacer)
|
||||||
|
i++
|
||||||
|
currentX += currentKeyXPos - currentX
|
||||||
|
}
|
||||||
|
currentX += row[i].mFullWidth
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if (currentX < mParams.mOccupiedWidth) {
|
||||||
|
// insert spacer
|
||||||
|
val spacer = KeyParams.newSpacer(mParams)
|
||||||
|
spacer.mRelativeWidth = (mParams.mOccupiedWidth - currentX) / mParams.mBaseWidth
|
||||||
|
spacer.mRelativeHeight = row.last().mRelativeHeight
|
||||||
|
spacer.yPos = row.last().yPos
|
||||||
|
row.add(spacer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addSplit() {
|
||||||
|
val spacerRelativeWidth = Settings.getInstance().current.mSpacerRelativeWidth
|
||||||
|
// adjust gaps for the whole keyboard, so it's the same for all rows
|
||||||
|
// todo: maybe remove? not sure if narrower gaps are desirable
|
||||||
|
mParams.mRelativeHorizontalGap *= 1f / (1f + spacerRelativeWidth)
|
||||||
|
mParams.mHorizontalGap = (mParams.mRelativeHorizontalGap * mParams.mId.mWidth).toInt()
|
||||||
|
var maxWidthBeforeSpacer = 0f
|
||||||
|
var maxWidthAfterSpacer = 0f
|
||||||
|
for (row in keysInRows) {
|
||||||
|
fillGapsWithSpacers(row)
|
||||||
|
val y = row.first().yPos // all have the same y, so this is fine
|
||||||
|
val relativeWidthSum = row.sumOf { it.mRelativeWidth } // sum up relative widths
|
||||||
|
val spacer = KeyParams.newSpacer(mParams)
|
||||||
|
spacer.mRelativeWidth = spacerRelativeWidth
|
||||||
|
spacer.mRelativeHeight = row.first().mRelativeHeight
|
||||||
|
// insert spacer before first key that starts right of the center (also consider gap)
|
||||||
|
var insertIndex = row.indexOfFirst { it.xPos > mParams.mOccupiedWidth / 2 }
|
||||||
|
.takeIf { it > -1 } ?: (row.size / 2) // fallback should never be needed, but better than having an error
|
||||||
|
if (row.any { it.mCode == Constants.CODE_SPACE }) {
|
||||||
|
val spaceLeft = row.single { it.mCode == Constants.CODE_SPACE }
|
||||||
|
reduceSymbolAndActionKeyWidth(row)
|
||||||
|
insertIndex = row.indexOf(spaceLeft) + 1
|
||||||
|
val widthBeforeSpace = row.subList(0, insertIndex - 1).sumOf { it.mRelativeWidth }
|
||||||
|
val widthAfterSpace = row.subList(insertIndex, row.size).sumOf { it.mRelativeWidth }
|
||||||
|
val spaceLeftWidth = (maxWidthBeforeSpacer - widthBeforeSpace).coerceAtLeast(mParams.mDefaultRelativeKeyWidth)
|
||||||
|
val spaceRightWidth = (maxWidthAfterSpacer - widthAfterSpace).coerceAtLeast(mParams.mDefaultRelativeKeyWidth)
|
||||||
|
val spacerWidth = spaceLeft.mRelativeWidth + spacerRelativeWidth - spaceLeftWidth - spaceRightWidth
|
||||||
|
if (spacerWidth > 0.05f) {
|
||||||
|
// only insert if the spacer has a reasonable width
|
||||||
|
val spaceRight = KeyParams(spaceLeft)
|
||||||
|
spaceLeft.mRelativeWidth = spaceLeftWidth
|
||||||
|
spaceRight.mRelativeWidth = spaceRightWidth
|
||||||
|
spacer.mRelativeWidth = spacerWidth
|
||||||
|
row.add(insertIndex, spaceRight)
|
||||||
|
row.add(insertIndex, spacer)
|
||||||
|
} else {
|
||||||
|
// otherwise increase space width, so other keys are resized properly
|
||||||
|
spaceLeft.mRelativeWidth += spacerWidth
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val widthBeforeSpacer = row.subList(0, insertIndex).sumOf { it.mRelativeWidth }
|
||||||
|
val widthAfterSpacer = row.subList(insertIndex, row.size).sumOf { it.mRelativeWidth }
|
||||||
|
maxWidthBeforeSpacer = maxWidthBeforeSpacer.coerceAtLeast(widthBeforeSpacer)
|
||||||
|
maxWidthAfterSpacer = maxWidthAfterSpacer.coerceAtLeast(widthAfterSpacer)
|
||||||
|
row.add(insertIndex, spacer)
|
||||||
|
}
|
||||||
|
// re-calculate relative widths
|
||||||
|
val relativeWidthSumNew = row.sumOf { it.mRelativeWidth }
|
||||||
|
val widthFactor = relativeWidthSum / relativeWidthSumNew
|
||||||
|
// re-calculate absolute sizes and positions
|
||||||
|
var currentX = 0f
|
||||||
|
row.forEach {
|
||||||
|
it.mRelativeWidth *= widthFactor
|
||||||
|
it.setDimensionsFromRelativeSize(currentX, y)
|
||||||
|
currentX += it.mFullWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reduce width of symbol and action key if in the row, and add this width to space to keep other key size constant
|
||||||
|
private fun reduceSymbolAndActionKeyWidth(row: ArrayList<KeyParams>) {
|
||||||
|
val spaceKey = row.first { it.mCode == Constants.CODE_SPACE }
|
||||||
|
val symbolKey = row.firstOrNull { it.mCode == Constants.CODE_SWITCH_ALPHA_SYMBOL }
|
||||||
|
val symbolKeyWidth = symbolKey?.mRelativeWidth ?: 0f
|
||||||
|
if (symbolKeyWidth > mParams.mDefaultRelativeKeyWidth) {
|
||||||
|
val widthToChange = symbolKey!!.mRelativeWidth - mParams.mDefaultRelativeKeyWidth
|
||||||
|
symbolKey.mRelativeWidth -= widthToChange
|
||||||
|
spaceKey.mRelativeWidth += widthToChange
|
||||||
|
}
|
||||||
|
val actionKey = row.firstOrNull { it.mBackgroundType == Key.BACKGROUND_TYPE_ACTION }
|
||||||
|
val actionKeyWidth = actionKey?.mRelativeWidth ?: 0f
|
||||||
|
if (actionKeyWidth > mParams.mDefaultRelativeKeyWidth * 1.1f) { // allow it to stay a little wider
|
||||||
|
val widthToChange = actionKey!!.mRelativeWidth - mParams.mDefaultRelativeKeyWidth * 1.1f
|
||||||
|
actionKey.mRelativeWidth -= widthToChange
|
||||||
|
spaceKey.mRelativeWidth += widthToChange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startKeyboard() {
|
||||||
|
mCurrentY += mParams.mTopPadding
|
||||||
|
mTopEdge = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startRow() {
|
||||||
|
mLeftEdge = true
|
||||||
|
mRightEdgeKey = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endRow() {
|
||||||
|
val rightEdgeKey = mRightEdgeKey
|
||||||
|
if (rightEdgeKey != null) {
|
||||||
|
rightEdgeKey.markAsRightEdge(mParams)
|
||||||
|
mCurrentY += rightEdgeKey.height + rightEdgeKey.verticalGap
|
||||||
|
mRightEdgeKey = null
|
||||||
|
}
|
||||||
|
mLeftEdge = false
|
||||||
|
mTopEdge = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endKey(key: Key) {
|
||||||
|
mParams.onAddKey(key)
|
||||||
|
if (mLeftEdge) {
|
||||||
|
key.markAsLeftEdge(mParams)
|
||||||
|
mLeftEdge = false
|
||||||
|
}
|
||||||
|
if (mTopEdge) {
|
||||||
|
key.markAsTopEdge(mParams)
|
||||||
|
}
|
||||||
|
mRightEdgeKey = key
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endKeyboard() {
|
||||||
|
mParams.removeRedundantMoreKeys()
|
||||||
|
// {@link #parseGridRows(XmlPullParser,boolean)} may populate keyboard rows higher than
|
||||||
|
// previously expected.
|
||||||
|
val actualHeight = mCurrentY - mParams.mVerticalGap + mParams.mBottomPadding
|
||||||
|
mParams.mOccupiedHeight = Math.max(mParams.mOccupiedHeight, actualHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addKeysToParams() {
|
||||||
|
// need to reset it, we need to sum it up to get the height nicely
|
||||||
|
// (though in the end we could just not touch it at all, final used value is the same as the one before resetting)
|
||||||
|
mCurrentY = 0
|
||||||
|
startKeyboard()
|
||||||
|
for (row in keysInRows) {
|
||||||
|
startRow()
|
||||||
|
for (keyParams in row) {
|
||||||
|
endKey(keyParams.createKey())
|
||||||
|
}
|
||||||
|
endRow()
|
||||||
|
}
|
||||||
|
endKeyboard()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BUILDER_TAG = "Keyboard.Builder"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adapted from Kotlin source: https://github.com/JetBrains/kotlin/blob/7a7d392b3470b38d42f80c896b7270678d0f95c3/libraries/stdlib/common/src/generated/_Collections.kt#L3004
|
||||||
|
private inline fun <T> Iterable<T>.sumOf(selector: (T) -> Float): Float {
|
||||||
|
var sum = 0f
|
||||||
|
for (element in this) {
|
||||||
|
sum += selector(element)
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
|
@ -217,11 +217,10 @@ public class KeyboardParams {
|
||||||
mRightPadding = (int) keyboardAttr.getFraction(
|
mRightPadding = (int) keyboardAttr.getFraction(
|
||||||
R.styleable.Keyboard_keyboardRightPadding, width, width, 0);
|
R.styleable.Keyboard_keyboardRightPadding, width, width, 0);
|
||||||
|
|
||||||
final int baseWidth = mOccupiedWidth - mLeftPadding - mRightPadding;
|
mBaseWidth = mOccupiedWidth - mLeftPadding - mRightPadding;
|
||||||
mBaseWidth = baseWidth;
|
|
||||||
mDefaultRelativeKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
mDefaultRelativeKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
||||||
1, 1, 1f / DEFAULT_KEYBOARD_COLUMNS);
|
1, 1, 1f / DEFAULT_KEYBOARD_COLUMNS);
|
||||||
mDefaultKeyWidth = (int) (mDefaultRelativeKeyWidth * baseWidth);
|
mDefaultKeyWidth = (int) (mDefaultRelativeKeyWidth * mBaseWidth);
|
||||||
|
|
||||||
// todo: maybe settings should not be accessed from here?
|
// todo: maybe settings should not be accessed from here?
|
||||||
if (Settings.getInstance().getCurrent().mNarrowKeyGaps) {
|
if (Settings.getInstance().getCurrent().mNarrowKeyGaps) {
|
||||||
|
@ -241,15 +240,14 @@ public class KeyboardParams {
|
||||||
mHorizontalGap = (int) (mRelativeHorizontalGap * width);
|
mHorizontalGap = (int) (mRelativeHorizontalGap * width);
|
||||||
mVerticalGap = (int) (mRelativeVerticalGap * height);
|
mVerticalGap = (int) (mRelativeVerticalGap * height);
|
||||||
|
|
||||||
final int baseHeight = mOccupiedHeight - mTopPadding - mBottomPadding + mVerticalGap;
|
mBaseHeight = mOccupiedHeight - mTopPadding - mBottomPadding + mVerticalGap;
|
||||||
mBaseHeight = baseHeight;
|
|
||||||
mDefaultRelativeRowHeight = ResourceUtils.getDimensionOrFraction(keyboardAttr,
|
mDefaultRelativeRowHeight = ResourceUtils.getDimensionOrFraction(keyboardAttr,
|
||||||
R.styleable.Keyboard_rowHeight, 1, 1f / DEFAULT_KEYBOARD_ROWS);
|
R.styleable.Keyboard_rowHeight, 1, 1f / DEFAULT_KEYBOARD_ROWS);
|
||||||
if (mDefaultRelativeRowHeight > 1) { // can be absolute size, in that case will be > 1
|
if (mDefaultRelativeRowHeight > 1) { // can be absolute size, in that case will be > 1
|
||||||
mDefaultRowHeight = (int) mDefaultRelativeRowHeight;
|
mDefaultRowHeight = (int) mDefaultRelativeRowHeight;
|
||||||
mDefaultRelativeRowHeight *= -1; // make it negative when it's absolute
|
mDefaultRelativeRowHeight *= -1; // make it negative when it's absolute
|
||||||
} else {
|
} else {
|
||||||
mDefaultRowHeight = (int) (mDefaultRelativeRowHeight * baseHeight);
|
mDefaultRowHeight = (int) (mDefaultRelativeRowHeight * mBaseHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
|
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
|
||||||
|
|
|
@ -38,8 +38,8 @@ public final class XmlKeyboardRow {
|
||||||
|
|
||||||
// TODO: Add keyActionFlags.
|
// TODO: Add keyActionFlags.
|
||||||
private static class RowAttributes {
|
private static class RowAttributes {
|
||||||
/** Default width of a key in this row. */
|
/** Default width of a key in this row, relative to keyboard width */
|
||||||
public final float mDefaultKeyWidth;
|
public final float mDefaultRelativeKeyWidth;
|
||||||
/** Default keyLabelFlags in this row. */
|
/** Default keyLabelFlags in this row. */
|
||||||
public final int mDefaultKeyLabelFlags;
|
public final int mDefaultKeyLabelFlags;
|
||||||
/** Default backgroundType for this row */
|
/** Default backgroundType for this row */
|
||||||
|
@ -49,13 +49,11 @@ public final class XmlKeyboardRow {
|
||||||
* Parse and create key attributes. This constructor is used to parse Row tag.
|
* Parse and create key attributes. This constructor is used to parse Row tag.
|
||||||
*
|
*
|
||||||
* @param keyAttr an attributes array of Row tag.
|
* @param keyAttr an attributes array of Row tag.
|
||||||
* @param defaultKeyWidth a default key width.
|
* @param defaultRelativeKeyWidth a default key width relative to keyboardWidth.
|
||||||
* @param keyboardWidth the keyboard width that is required to calculate keyWidth attribute.
|
|
||||||
*/
|
*/
|
||||||
public RowAttributes(final TypedArray keyAttr, final float defaultKeyWidth,
|
public RowAttributes(final TypedArray keyAttr, final float defaultRelativeKeyWidth) {
|
||||||
final int keyboardWidth) {
|
mDefaultRelativeKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
||||||
mDefaultKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
1, 1, defaultRelativeKeyWidth);
|
||||||
keyboardWidth, keyboardWidth, defaultKeyWidth);
|
|
||||||
mDefaultKeyLabelFlags = keyAttr.getInt(R.styleable.Keyboard_Key_keyLabelFlags, 0);
|
mDefaultKeyLabelFlags = keyAttr.getInt(R.styleable.Keyboard_Key_keyLabelFlags, 0);
|
||||||
mDefaultBackgroundType = keyAttr.getInt(R.styleable.Keyboard_Key_backgroundType,
|
mDefaultBackgroundType = keyAttr.getInt(R.styleable.Keyboard_Key_backgroundType,
|
||||||
Key.BACKGROUND_TYPE_NORMAL);
|
Key.BACKGROUND_TYPE_NORMAL);
|
||||||
|
@ -67,12 +65,10 @@ public final class XmlKeyboardRow {
|
||||||
*
|
*
|
||||||
* @param keyAttr an attributes array of include tag.
|
* @param keyAttr an attributes array of include tag.
|
||||||
* @param defaultRowAttr default Row attributes.
|
* @param defaultRowAttr default Row attributes.
|
||||||
* @param keyboardWidth the keyboard width that is required to calculate keyWidth attribute.
|
|
||||||
*/
|
*/
|
||||||
public RowAttributes(final TypedArray keyAttr, final RowAttributes defaultRowAttr,
|
public RowAttributes(final TypedArray keyAttr, final RowAttributes defaultRowAttr) {
|
||||||
final int keyboardWidth) {
|
mDefaultRelativeKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
||||||
mDefaultKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
1, 1, defaultRowAttr.mDefaultRelativeKeyWidth);
|
||||||
keyboardWidth, keyboardWidth, defaultRowAttr.mDefaultKeyWidth);
|
|
||||||
mDefaultKeyLabelFlags = keyAttr.getInt(R.styleable.Keyboard_Key_keyLabelFlags, 0)
|
mDefaultKeyLabelFlags = keyAttr.getInt(R.styleable.Keyboard_Key_keyLabelFlags, 0)
|
||||||
| defaultRowAttr.mDefaultKeyLabelFlags;
|
| defaultRowAttr.mDefaultKeyLabelFlags;
|
||||||
mDefaultBackgroundType = keyAttr.getInt(R.styleable.Keyboard_Key_backgroundType,
|
mDefaultBackgroundType = keyAttr.getInt(R.styleable.Keyboard_Key_backgroundType,
|
||||||
|
@ -101,8 +97,7 @@ public final class XmlKeyboardRow {
|
||||||
}
|
}
|
||||||
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.Keyboard_Key);
|
R.styleable.Keyboard_Key);
|
||||||
mRowAttributesStack.push(new RowAttributes(
|
mRowAttributesStack.push(new RowAttributes(keyAttr, params.mDefaultRelativeKeyWidth));
|
||||||
keyAttr, params.mDefaultKeyWidth, params.mBaseWidth));
|
|
||||||
keyAttr.recycle();
|
keyAttr.recycle();
|
||||||
|
|
||||||
mCurrentY = y;
|
mCurrentY = y;
|
||||||
|
@ -114,8 +109,7 @@ public final class XmlKeyboardRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushRowAttributes(final TypedArray keyAttr) {
|
public void pushRowAttributes(final TypedArray keyAttr) {
|
||||||
final RowAttributes newAttributes = new RowAttributes(
|
final RowAttributes newAttributes = new RowAttributes(keyAttr, mRowAttributesStack.peek());
|
||||||
keyAttr, mRowAttributesStack.peek(), mParams.mBaseWidth);
|
|
||||||
mRowAttributesStack.push(newAttributes);
|
mRowAttributesStack.push(newAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +117,8 @@ public final class XmlKeyboardRow {
|
||||||
mRowAttributesStack.pop();
|
mRowAttributesStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getDefaultKeyWidth() {
|
public float getDefaultRelativeKeyWidth() {
|
||||||
return mRowAttributesStack.peek().mDefaultKeyWidth;
|
return mRowAttributesStack.peek().mDefaultRelativeKeyWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultKeyLabelFlags() {
|
public int getDefaultKeyLabelFlags() {
|
||||||
|
@ -167,30 +161,24 @@ public final class XmlKeyboardRow {
|
||||||
|
|
||||||
public float getRelativeKeyWidth(final TypedArray keyAttr) {
|
public float getRelativeKeyWidth(final TypedArray keyAttr) {
|
||||||
if (keyAttr == null)
|
if (keyAttr == null)
|
||||||
return mParams.mDefaultRelativeKeyWidth;
|
return getDefaultRelativeKeyWidth();
|
||||||
final int widthType = ResourceUtils.getEnumValue(keyAttr,
|
final int widthType = ResourceUtils.getEnumValue(keyAttr,
|
||||||
R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
|
R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
|
||||||
if (widthType == KEYWIDTH_FILL_RIGHT)
|
if (widthType == KEYWIDTH_FILL_RIGHT)
|
||||||
return -1;
|
return -1f;
|
||||||
|
// else KEYWIDTH_NOT_ENUM
|
||||||
return keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
return keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
||||||
1, 1, mParams.mDefaultRelativeKeyWidth);
|
1, 1, getDefaultRelativeKeyWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getKeyWidth(final TypedArray keyAttr, final float keyXPos) {
|
public float getKeyWidth(final TypedArray keyAttr, final float keyXPos) {
|
||||||
if (keyAttr == null) {
|
final float relativeWidth = getRelativeKeyWidth(keyAttr);
|
||||||
return getDefaultKeyWidth();
|
if (relativeWidth == -1f) {
|
||||||
}
|
|
||||||
final int widthType = ResourceUtils.getEnumValue(keyAttr,
|
|
||||||
R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
|
|
||||||
switch (widthType) {
|
|
||||||
case KEYWIDTH_FILL_RIGHT:
|
|
||||||
// If keyWidth is fillRight, the actual key width will be determined to fill
|
// If keyWidth is fillRight, the actual key width will be determined to fill
|
||||||
// out the area up to the right edge of the keyboard.
|
// out the area up to the right edge of the keyboard.
|
||||||
final int keyboardRightEdge = mParams.mOccupiedWidth - mParams.mRightPadding;
|
final int keyboardRightEdge = mParams.mOccupiedWidth - mParams.mRightPadding;
|
||||||
return keyboardRightEdge - keyXPos;
|
return keyboardRightEdge - keyXPos;
|
||||||
default: // KEYWIDTH_NOT_ENUM
|
}
|
||||||
return keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
|
return relativeWidth * mParams.mBaseWidth;
|
||||||
mParams.mBaseWidth, mParams.mBaseWidth, getDefaultKeyWidth());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.*
|
||||||
* "Appearance" settings sub screen.
|
* "Appearance" settings sub screen.
|
||||||
*/
|
*/
|
||||||
class AppearanceSettingsFragment : SubScreenFragment() {
|
class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
|
|
||||||
private var needsReload = false
|
private var needsReload = false
|
||||||
|
|
||||||
private val stylePref: ListPreference by lazy { preferenceScreen.findPreference(Settings.PREF_THEME_STYLE)!! }
|
private val stylePref: ListPreference by lazy { preferenceScreen.findPreference(Settings.PREF_THEME_STYLE)!! }
|
||||||
|
@ -30,17 +29,26 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
private val dayNightPref: TwoStatePreference? by lazy { preferenceScreen.findPreference(Settings.PREF_THEME_DAY_NIGHT) }
|
private val dayNightPref: TwoStatePreference? by lazy { preferenceScreen.findPreference(Settings.PREF_THEME_DAY_NIGHT) }
|
||||||
private val userColorsPref: Preference by lazy { preferenceScreen.findPreference("theme_select_colors")!! }
|
private val userColorsPref: Preference by lazy { preferenceScreen.findPreference("theme_select_colors")!! }
|
||||||
private val userColorsPrefNight: Preference? by lazy { preferenceScreen.findPreference("theme_select_colors_night") }
|
private val userColorsPrefNight: Preference? by lazy { preferenceScreen.findPreference("theme_select_colors_night") }
|
||||||
|
private val splitPref: TwoStatePreference? by lazy { preferenceScreen.findPreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD) }
|
||||||
|
private val splitScalePref: Preference? by lazy { preferenceScreen.findPreference(Settings.PREF_SPLIT_SPACER_SCALE) }
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
override fun onCreate(icicle: Bundle?) {
|
super.onCreate(savedInstanceState)
|
||||||
super.onCreate(icicle)
|
|
||||||
addPreferencesFromResource(R.xml.prefs_screen_appearance)
|
addPreferencesFromResource(R.xml.prefs_screen_appearance)
|
||||||
|
|
||||||
removeUnsuitablePreferences()
|
removeUnsuitablePreferences()
|
||||||
setupTheme()
|
setupTheme()
|
||||||
setThemeVariantPrefs(sharedPreferences.getString(Settings.PREF_THEME_STYLE, KeyboardTheme.STYLE_MATERIAL)!!)
|
setThemeVariantPrefs(sharedPreferences.getString(Settings.PREF_THEME_STYLE, KeyboardTheme.STYLE_MATERIAL)!!)
|
||||||
|
|
||||||
setupKeyboardHeight(Settings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE)
|
setupScalePrefs(Settings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE)
|
||||||
|
if (splitScalePref != null) {
|
||||||
|
setupScalePrefs(Settings.PREF_SPLIT_SPACER_SCALE, SettingsValues.DEFAULT_SIZE_SCALE)
|
||||||
|
splitScalePref?.isVisible = splitPref?.isChecked == true
|
||||||
|
splitPref?.setOnPreferenceChangeListener { _, value ->
|
||||||
|
splitScalePref?.isVisible = value as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
@ -52,7 +60,7 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(prefs: SharedPreferences?, key: String?) {
|
override fun onSharedPreferenceChanged(prefs: SharedPreferences?, key: String?) {
|
||||||
super.onSharedPreferenceChanged(prefs, key)
|
super.onSharedPreferenceChanged(prefs, key)
|
||||||
needsReload = true // may not always be the necessary, but that's ok
|
needsReload = true // may not always necessary, but that's ok
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeUnsuitablePreferences() {
|
private fun removeUnsuitablePreferences() {
|
||||||
|
@ -79,6 +87,7 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
val heightDp = metrics.heightPixels / metrics.density
|
val heightDp = metrics.heightPixels / metrics.density
|
||||||
if (!ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED || (min(widthDp, heightDp) < 600 && max(widthDp, heightDp) < 720)) {
|
if (!ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED || (min(widthDp, heightDp) < 600 && max(widthDp, heightDp) < 720)) {
|
||||||
removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD)
|
removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD)
|
||||||
|
removePreference(Settings.PREF_SPLIT_SPACER_SCALE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +149,7 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
userColorsPrefNight?.isVisible = dayNightPref?.isChecked == true && colorsNightPref?.value == KeyboardTheme.THEME_USER_NIGHT
|
userColorsPrefNight?.isVisible = dayNightPref?.isChecked == true && colorsNightPref?.value == KeyboardTheme.THEME_USER_NIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupKeyboardHeight(prefKey: String, defaultValue: Float) {
|
private fun setupScalePrefs(prefKey: String, defaultValue: Float) {
|
||||||
val prefs = sharedPreferences
|
val prefs = sharedPreferences
|
||||||
val pref = findPreference(prefKey) as? SeekBarDialogPreference
|
val pref = findPreference(prefKey) as? SeekBarDialogPreference
|
||||||
pref?.setInterface(object : SeekBarDialogPreference.ValueProxy {
|
pref?.setInterface(object : SeekBarDialogPreference.ValueProxy {
|
||||||
|
@ -149,13 +158,11 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
||||||
|
|
||||||
private fun getPercentageFromValue(floatValue: Float) = (floatValue * PERCENTAGE_FLOAT).toInt()
|
private fun getPercentageFromValue(floatValue: Float) = (floatValue * PERCENTAGE_FLOAT).toInt()
|
||||||
|
|
||||||
override fun writeValue(value: Int, key: String) = prefs.edit()
|
override fun writeValue(value: Int, key: String) = prefs.edit().putFloat(key, getValueFromPercentage(value)).apply()
|
||||||
.putFloat(key, getValueFromPercentage(value)).apply()
|
|
||||||
|
|
||||||
override fun writeDefaultValue(key: String) = prefs.edit().remove(key).apply()
|
override fun writeDefaultValue(key: String) = prefs.edit().remove(key).apply()
|
||||||
|
|
||||||
override fun readValue(key: String) = getPercentageFromValue(
|
override fun readValue(key: String) = getPercentageFromValue(prefs.getFloat(prefKey, defaultValue))
|
||||||
Settings.readKeyboardHeight(prefs, defaultValue))
|
|
||||||
|
|
||||||
override fun readDefaultValue(key: String) = getPercentageFromValue(defaultValue)
|
override fun readDefaultValue(key: String) = getPercentageFromValue(defaultValue)
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static final String PREF_SHOW_EMOJI_KEY = "pref_show_emoji_key";
|
public static final String PREF_SHOW_EMOJI_KEY = "pref_show_emoji_key";
|
||||||
public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
|
public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
|
||||||
public static final String PREF_ENABLE_SPLIT_KEYBOARD = "pref_split_keyboard";
|
public static final String PREF_ENABLE_SPLIT_KEYBOARD = "pref_split_keyboard";
|
||||||
|
public static final String PREF_SPLIT_SPACER_SCALE = "pref_split_spacer_scale";
|
||||||
public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale";
|
public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale";
|
||||||
public static final String PREF_SPACE_TRACKPAD = "pref_space_trackpad";
|
public static final String PREF_SPACE_TRACKPAD = "pref_space_trackpad";
|
||||||
public static final String PREF_DELETE_SWIPE = "pref_delete_swipe";
|
public static final String PREF_DELETE_SWIPE = "pref_delete_swipe";
|
||||||
|
@ -341,13 +342,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
return res.getInteger(R.integer.config_clipboard_history_retention_time);
|
return res.getInteger(R.integer.config_clipboard_history_retention_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float readKeyboardHeight(final SharedPreferences prefs,
|
|
||||||
final float defaultValue) {
|
|
||||||
final float percentage = prefs.getFloat(
|
|
||||||
Settings.PREF_KEYBOARD_HEIGHT_SCALE, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
|
||||||
return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean readSpaceTrackpadEnabled(final SharedPreferences prefs) {
|
public static boolean readSpaceTrackpadEnabled(final SharedPreferences prefs) {
|
||||||
return prefs.getBoolean(PREF_SPACE_TRACKPAD, true);
|
return prefs.getBoolean(PREF_SPACE_TRACKPAD, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,7 @@ public class SettingsValues {
|
||||||
public final boolean mShouldShowLxxSuggestionUi;
|
public final boolean mShouldShowLxxSuggestionUi;
|
||||||
// Use split layout for keyboard.
|
// Use split layout for keyboard.
|
||||||
public final boolean mIsSplitKeyboardEnabled;
|
public final boolean mIsSplitKeyboardEnabled;
|
||||||
|
public final float mSpacerRelativeWidth;
|
||||||
public final int mScreenMetrics;
|
public final int mScreenMetrics;
|
||||||
public final boolean mAddToPersonalDictionary;
|
public final boolean mAddToPersonalDictionary;
|
||||||
public final boolean mUseContactsDictionary;
|
public final boolean mUseContactsDictionary;
|
||||||
|
@ -162,7 +163,12 @@ public class SettingsValues {
|
||||||
mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
|
mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
|
||||||
mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
|
mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
|
||||||
mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration());
|
mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration());
|
||||||
mIsSplitKeyboardEnabled = prefs.getBoolean(Settings.PREF_ENABLE_SPLIT_KEYBOARD, false);
|
final float displayWidthDp = res.getDisplayMetrics().widthPixels / res.getDisplayMetrics().density;
|
||||||
|
mIsSplitKeyboardEnabled = prefs.getBoolean(Settings.PREF_ENABLE_SPLIT_KEYBOARD, false) && displayWidthDp > 600; // require display width of 600 dp for split
|
||||||
|
// determine spacerWidth from display width and scale setting
|
||||||
|
mSpacerRelativeWidth = mIsSplitKeyboardEnabled
|
||||||
|
? Math.min(Math.max((displayWidthDp - 600) / 6000f + 0.15f, 0.15f), 0.25f) * prefs.getFloat(Settings.PREF_SPLIT_SPACER_SCALE, DEFAULT_SIZE_SCALE)
|
||||||
|
: 0f;
|
||||||
mScreenMetrics = Settings.readScreenMetrics(res);
|
mScreenMetrics = Settings.readScreenMetrics(res);
|
||||||
|
|
||||||
mShouldShowLxxSuggestionUi = Settings.SHOULD_SHOW_LXX_SUGGESTION_UI
|
mShouldShowLxxSuggestionUi = Settings.SHOULD_SHOW_LXX_SUGGESTION_UI
|
||||||
|
@ -188,7 +194,7 @@ public class SettingsValues {
|
||||||
readSuggestionsEnabled(prefs);
|
readSuggestionsEnabled(prefs);
|
||||||
mIncognitoModeEnabled = Settings.readAlwaysIncognitoMode(prefs) || mInputAttributes.mNoLearning
|
mIncognitoModeEnabled = Settings.readAlwaysIncognitoMode(prefs) || mInputAttributes.mNoLearning
|
||||||
|| mInputAttributes.mIsPasswordField;
|
|| mInputAttributes.mIsPasswordField;
|
||||||
mKeyboardHeightScale = Settings.readKeyboardHeight(prefs, DEFAULT_SIZE_SCALE);
|
mKeyboardHeightScale = prefs.getFloat(Settings.PREF_KEYBOARD_HEIGHT_SCALE, DEFAULT_SIZE_SCALE);
|
||||||
mDisplayOrientation = res.getConfiguration().orientation;
|
mDisplayOrientation = res.getConfiguration().orientation;
|
||||||
mAppWorkarounds = new AsyncResultHolder<>("AppWorkarounds");
|
mAppWorkarounds = new AsyncResultHolder<>("AppWorkarounds");
|
||||||
final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo(
|
final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo(
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
<string name="settings_category_miscellaneous">Miscellaneous</string>
|
<string name="settings_category_miscellaneous">Miscellaneous</string>
|
||||||
<!-- Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
|
<!-- Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
|
||||||
<string name="enable_split_keyboard">Enable split keyboard</string>
|
<string name="enable_split_keyboard">Enable split keyboard</string>
|
||||||
|
<!-- Option for setting distance for split keyboard -->
|
||||||
|
<string name="split_spacer_scale">Split distance</string>
|
||||||
<!-- Option name for including other IMEs in the language key switch list [CHAR LIMIT=30] -->
|
<!-- Option name for including other IMEs in the language key switch list [CHAR LIMIT=30] -->
|
||||||
<string name="language_switch_key_switch_input_method">Switch to other input methods</string>
|
<string name="language_switch_key_switch_input_method">Switch to other input methods</string>
|
||||||
<!-- Option name for switching language / subtype only [CHAR LIMIT=30] -->
|
<!-- Option name for switching language / subtype only [CHAR LIMIT=30] -->
|
||||||
|
|
|
@ -63,6 +63,12 @@
|
||||||
android:persistent="true"
|
android:persistent="true"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
|
|
||||||
|
<org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference
|
||||||
|
android:key="pref_split_spacer_scale"
|
||||||
|
android:title="@string/split_spacer_scale"
|
||||||
|
latin:minValue="50"
|
||||||
|
latin:maxValue="200" /> <!-- percentage -->
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:key="pref_narrow_key_gaps"
|
android:key="pref_narrow_key_gaps"
|
||||||
android:title="@string/prefs_narrow_key_gaps"
|
android:title="@string/prefs_narrow_key_gaps"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue