diff --git a/app/src/main/java/eur/cfpifpsi/titanboard/TitanboardIME.java b/app/src/main/java/eur/cfpifpsi/titanboard/TitanboardIME.java index aeb1669..f2d373e 100644 --- a/app/src/main/java/eur/cfpifpsi/titanboard/TitanboardIME.java +++ b/app/src/main/java/eur/cfpifpsi/titanboard/TitanboardIME.java @@ -32,6 +32,8 @@ import android.view.inputmethod.InputConnection; import java.util.ArrayList; +import eur.cfpifpsi.titanboard.views.InputView; + // TODO: Revamp the keymap system — separate device keymap, keymap types (12-key, alphabetic, etc.) // TODO: Add auto-capitalization // TODO: Add auto-periods @@ -218,7 +220,7 @@ public class TitanboardIME extends InputMethodService { @Override public void onFinishInput() { mMetaKeyManager.resetMetaKeyState(); - mInputView.mClipboardPopup.dismiss(); + mInputView.mPopup.dismiss(); } // Cyclers & runnables diff --git a/app/src/main/java/eur/cfpifpsi/titanboard/views/ClipboardView.java b/app/src/main/java/eur/cfpifpsi/titanboard/views/ClipboardView.java new file mode 100644 index 0000000..bdc3bd1 --- /dev/null +++ b/app/src/main/java/eur/cfpifpsi/titanboard/views/ClipboardView.java @@ -0,0 +1,81 @@ +/* + * An input method for physical keyboard phones + * Copyright (C) 2024 Emil Kosz + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package eur.cfpifpsi.titanboard.views; + +import android.annotation.TargetApi; +import android.content.ClipData; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ScrollView; + +import java.util.ArrayList; + +import eur.cfpifpsi.titanboard.R; +import eur.cfpifpsi.titanboard.TitanboardIME; + +public class ClipboardView extends ScrollView { + private final TitanboardIME mTitanboardIME; + private final LinearLayout.LayoutParams mClipLayout; + private LinearLayout mClipList; + + public ClipboardView(Context context, AttributeSet attrs) { + super(context, attrs, 0); + mTitanboardIME = (TitanboardIME) context; + mClipLayout = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, 0); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mClipList = findViewById(R.id.clip_list); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void setClips(ArrayList items) { + int size = items.size(); + for (int i = 0; i < size; ++i) { + ClipData.Item item = items.get(i); + LinearLayout clipView = (LinearLayout) mClipList.getChildAt(i); + + if (clipView == null) { + clipView = (LinearLayout) inflate(getContext(), R.layout.clip, null); + clipView.setTag(i); + clipView.setLayoutParams(mClipLayout); + mClipList.addView(clipView); + } + + Button pasteButton = clipView.findViewById(R.id.paste_button); + pasteButton.setText(item.getText()); + pasteButton.setOnClickListener(button -> mTitanboardIME.getCurrentInputConnection() + .commitText(item.getText(), 1)); + + LinearLayout finalClipView = clipView; + clipView.findViewById(R.id.button_delete).setOnClickListener(button -> { + mClipList.removeView(finalClipView); + mTitanboardIME.mClipManager.removeItem(item); + }); + } + } +} diff --git a/app/src/main/java/eur/cfpifpsi/titanboard/InputView.java b/app/src/main/java/eur/cfpifpsi/titanboard/views/InputView.java similarity index 52% rename from app/src/main/java/eur/cfpifpsi/titanboard/InputView.java rename to app/src/main/java/eur/cfpifpsi/titanboard/views/InputView.java index c1a6097..1a122c3 100644 --- a/app/src/main/java/eur/cfpifpsi/titanboard/InputView.java +++ b/app/src/main/java/eur/cfpifpsi/titanboard/views/InputView.java @@ -16,65 +16,55 @@ * along with this program. If not, see . */ -package eur.cfpifpsi.titanboard; +package eur.cfpifpsi.titanboard.views; import android.annotation.TargetApi; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.graphics.Paint; -import android.graphics.Typeface; import android.os.Build; import android.util.AttributeSet; -import android.view.ViewGroup; import android.widget.Button; -import android.widget.HorizontalScrollView; import android.widget.ImageButton; -import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.RelativeLayout; -import android.widget.ScrollView; -import android.widget.TextView; import java.util.ArrayList; -// TODO: programmatically scroll if current selected symbol is outside the visible space of the -// scrollview +import eur.cfpifpsi.titanboard.KeymapManager; +import eur.cfpifpsi.titanboard.MetaKeyManager; +import eur.cfpifpsi.titanboard.R; +import eur.cfpifpsi.titanboard.SettingsActivity; +import eur.cfpifpsi.titanboard.TitanboardIME; public final class InputView extends RelativeLayout { private final int[] buttonStateToggled = {R.attr.state_toggled}; private final TitanboardIME mTitanboardIME; - private final LinearLayout.LayoutParams mSymbolLayout; - private final LinearLayout.LayoutParams mClipLayout; - public PopupWindow mClipboardPopup; - private LinearLayout mSymbolList; - private LinearLayout mClipList; + public PopupWindow mPopup; private Button mStateButton; private ImageButton mClipboardButton; + private SymbolsView mSymbolsView; + private ClipboardView mClipboardView; public InputView(Context context, AttributeSet attrs) { super(context, attrs, 0); mTitanboardIME = (TitanboardIME) context; - mSymbolLayout = new LinearLayout.LayoutParams( - getResources().getDimensionPixelSize(R.dimen.symbol_width), - ViewGroup.LayoutParams.MATCH_PARENT, 0); - mClipLayout = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, 0); } @Override protected void onFinishInflate() { super.onFinishInflate(); - mSymbolList = findViewById(R.id.symbol_list); mStateButton = findViewById(R.id.state_button); mClipboardButton = findViewById(R.id.clipboard_button); - ScrollView mClipboardView = (ScrollView) inflate(getContext(), R.layout.clipboard, null); - mClipList = mClipboardView.findViewById(R.id.clip_list); - mClipboardPopup = new PopupWindow(mClipboardView, + + mSymbolsView = findViewById(R.id.symbols_view); + mClipboardView = (ClipboardView) inflate(getContext(), R.layout.clipboard, null); + + mPopup = new PopupWindow(mClipboardView, getResources().getDimensionPixelSize(R.dimen.clipboard_popup_width), getResources().getDimensionPixelSize(R.dimen.clipboard_popup_height), true); - mClipboardPopup.setOnDismissListener(() -> mClipboardButton.setImageState(null, true)); + mPopup.setOnDismissListener(() -> mClipboardButton.setImageState(null, true)); mStateButton.setOnClickListener(button -> { MetaKeyManager metaManager = mTitanboardIME.mMetaKeyManager; @@ -96,8 +86,8 @@ public final class InputView extends RelativeLayout { }); mClipboardButton.setOnClickListener(button -> { - mClipboardPopup.showAsDropDown(mClipboardButton, - -(mClipboardPopup.getWidth() - mClipboardButton.getWidth()) / 2, 0); + mPopup.showAsDropDown(mClipboardButton, + -(mPopup.getWidth() - mClipboardButton.getWidth()) / 2, 0); mClipboardButton.setImageState(buttonStateToggled, true); }); @@ -149,83 +139,19 @@ public final class InputView extends RelativeLayout { mStateButton.setText(keymapManager.getCurrentLabel()); } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void setClips(ArrayList items) { - int size = items.size(); - for (int i = 0; i < size; ++i) { - ClipData.Item item = items.get(i); - LinearLayout clipView = (LinearLayout) mClipList.getChildAt(i); - - if (clipView == null) { - clipView = (LinearLayout) inflate(getContext(), R.layout.clip, null); - clipView.setTag(i); - clipView.setLayoutParams(mClipLayout); - mClipList.addView(clipView); - } - - Button pasteButton = clipView.findViewById(R.id.paste_button); - pasteButton.setText(item.getText()); - pasteButton.setOnClickListener(button -> mTitanboardIME.getCurrentInputConnection() - .commitText(item.getText(), 1)); - - LinearLayout finalClipView = clipView; - clipView.findViewById(R.id.button_delete).setOnClickListener(button -> { - mClipList.removeView(finalClipView); - mTitanboardIME.mClipManager.removeItem(item); - }); - } + mClipboardView.setClips(items); } public void setSymbolsVisible(boolean state) { - mSymbolList.setVisibility(state ? VISIBLE : GONE); + mSymbolsView.setSymbolsVisible(state); } - /** - * @noinspection MethodWithMultipleLoops - */ public void setSymbols(ArrayList strings) { - int size = strings.size(); - for (int i = 0; i < size; ++i) { - TextView tv = (TextView) mSymbolList.getChildAt(i); - - if (tv == null) { - tv = (TextView) inflate(getContext(), R.layout.symbol, null); - tv.setTag(i); - tv.setLayoutParams(mSymbolLayout); - mSymbolList.addView(tv); - } - - tv.setText(strings.get(i)); - tv.setVisibility(VISIBLE); - } - - int childCount = mSymbolList.getChildCount(); - for (int i = size; i < childCount; ++i) { - mSymbolList.getChildAt(i).setVisibility(GONE); - } + mSymbolsView.setSymbols(strings); } public void setSelectedSymbol(int index) { - int childCount = mSymbolList.getChildCount(); - for (int i = 0; i < childCount; ++i) { - TextView tv = (TextView) mSymbolList.getChildAt(i); - - if (i == index) { - HorizontalScrollView hsw = findViewById(R.id.symbol_list_container); - tv.setPressed(true); - tv.setTypeface(null, Typeface.BOLD); - // This, if the symbol list is larger than the scroll view, scrolls it just to show - // the selected symbol at the very end. It isn't really necessary, as it's a rarity - // that a key has more than five symbols, but perhaps someone will want to add a - // keymap that has a lot of symbols under one key, and also this is a safeguard for - // smaller screen sizes. - hsw.smoothScrollTo(tv.getRight() - + (getResources().getDimensionPixelSize(R.dimen.default_space) << 1) - - hsw.getRight(), 0); - } else { - tv.setPressed(false); - tv.setTypeface(null, Typeface.NORMAL); - } - } + mSymbolsView.setSelectedSymbol(index); } } diff --git a/app/src/main/java/eur/cfpifpsi/titanboard/views/SymbolsView.java b/app/src/main/java/eur/cfpifpsi/titanboard/views/SymbolsView.java new file mode 100644 index 0000000..a544018 --- /dev/null +++ b/app/src/main/java/eur/cfpifpsi/titanboard/views/SymbolsView.java @@ -0,0 +1,100 @@ +/* + * An input method for physical keyboard phones + * Copyright (C) 2024 Emil Kosz + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package eur.cfpifpsi.titanboard.views; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.util.ArrayList; + +import eur.cfpifpsi.titanboard.R; + +public class SymbolsView extends HorizontalScrollView { + private final LinearLayout.LayoutParams mSymbolLayout; + private LinearLayout mSymbolList; + + public SymbolsView(Context context, AttributeSet attrs) { + super(context, attrs, 0); + mSymbolLayout = new LinearLayout.LayoutParams( + getResources().getDimensionPixelSize(R.dimen.symbol_width), + LinearLayout.LayoutParams.MATCH_PARENT, 0); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mSymbolList = findViewById(R.id.symbol_list); + } + + public void setSymbolsVisible(boolean state) { + mSymbolList.setVisibility(state ? VISIBLE : GONE); + } + + /** + * @noinspection MethodWithMultipleLoops + */ + public void setSymbols(ArrayList strings) { + int size = strings.size(); + for (int i = 0; i < size; ++i) { + TextView tv = (TextView) mSymbolList.getChildAt(i); + + if (tv == null) { + tv = (TextView) inflate(getContext(), R.layout.symbol, null); + tv.setTag(i); + tv.setLayoutParams(mSymbolLayout); + mSymbolList.addView(tv); + } + + tv.setText(strings.get(i)); + tv.setVisibility(VISIBLE); + } + + int childCount = mSymbolList.getChildCount(); + for (int i = size; i < childCount; ++i) { + mSymbolList.getChildAt(i).setVisibility(GONE); + } + } + + public void setSelectedSymbol(int index) { + int childCount = mSymbolList.getChildCount(); + for (int i = 0; i < childCount; ++i) { + TextView tv = (TextView) mSymbolList.getChildAt(i); + + if (i == index) { + tv.setPressed(true); + tv.setTypeface(null, Typeface.BOLD); + // This, if the symbol list is larger than the scroll view, scrolls it just to show + // the selected symbol at the very end. It isn't really necessary, as it's a rarity + // that a key has more than five symbols, but perhaps someone will want to add a + // keymap that has a lot of symbols under one key, and also this is a safeguard for + // smaller screen sizes. + smoothScrollTo(tv.getRight() + + (getResources().getDimensionPixelSize(R.dimen.default_space) << 1) + - getRight(), 0); + } else { + tv.setPressed(false); + tv.setTypeface(null, Typeface.NORMAL); + } + } + } +} diff --git a/app/src/main/res/layout/clipboard.xml b/app/src/main/res/layout/clipboard.xml index 67c7a13..6548302 100644 --- a/app/src/main/res/layout/clipboard.xml +++ b/app/src/main/res/layout/clipboard.xml @@ -16,7 +16,7 @@ ~ along with this program. If not, see . --> - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/input.xml b/app/src/main/res/layout/input.xml index 848e9df..199e330 100644 --- a/app/src/main/res/layout/input.xml +++ b/app/src/main/res/layout/input.xml @@ -16,7 +16,7 @@ ~ along with this program. If not, see . --> - - - + - \ No newline at end of file + \ No newline at end of file