Clipboard managment pretty much finished
This commit is contained in:
+28
-16
@@ -25,15 +25,16 @@ import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public class ClipboardHandler implements ClipboardManager.OnPrimaryClipChangedListener {
|
||||
public class ClipManager extends ArrayList<ClipData.Item>
|
||||
implements ClipboardManager.OnPrimaryClipChangedListener {
|
||||
private final InputMethod mInputMethod;
|
||||
private final ClipboardManager mClipboardManager;
|
||||
private ArrayDeque<ClipData> mClips = new ArrayDeque<>();
|
||||
private long mLastCallbackTimestamp;
|
||||
|
||||
public ClipboardHandler(Context context) {
|
||||
public ClipManager(Context context) {
|
||||
mInputMethod = (InputMethod) context;
|
||||
mClipboardManager = (ClipboardManager) mInputMethod.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mClipboardManager.addPrimaryClipChangedListener(this);
|
||||
@@ -41,20 +42,31 @@ public class ClipboardHandler implements ClipboardManager.OnPrimaryClipChangedLi
|
||||
|
||||
@Override
|
||||
public void onPrimaryClipChanged() {
|
||||
// The callback can be launched several times, so we have to check if it isn't the same
|
||||
// clipboard data.
|
||||
if (mClips.peekFirst() != null) {
|
||||
if (mClips.peekFirst().equals(mClipboardManager.getPrimaryClip())) {
|
||||
return;
|
||||
// The callback can be launched several times at once, so we have to check if it isn't the
|
||||
// same clipboard data.
|
||||
if (System.currentTimeMillis() - mLastCallbackTimestamp < 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLastCallbackTimestamp = System.currentTimeMillis();
|
||||
ClipData clip = mClipboardManager.getPrimaryClip();
|
||||
|
||||
if (clip == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < clip.getItemCount(); ++i) {
|
||||
ClipData.Item item = clip.getItemAt(i);
|
||||
// We do not support non-text clips for now, so all we add are text clips.
|
||||
if (item.getText() != null) {
|
||||
add(0, item);
|
||||
}
|
||||
|
||||
if (size() > mInputMethod.mPreferenceHolder.getMaxClipboardItems()) {
|
||||
remove(size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
mClips.addFirst(mClipboardManager.getPrimaryClip());
|
||||
|
||||
if (mClips.size() > mInputMethod.mPreferenceHolder.getMaxClipboardItems()) {
|
||||
mClips.removeLast();
|
||||
}
|
||||
|
||||
mInputMethod.mInputView.setClips(mClips.toArray());
|
||||
mInputMethod.mInputView.setClips(this);
|
||||
}
|
||||
}
|
||||
@@ -45,12 +45,12 @@ public class InputMethod extends InputMethodService {
|
||||
public MetaKeyManager mMetaKeyManager;
|
||||
public KeymapManager mKeymapManager;
|
||||
public PreferenceHolder mPreferenceHolder;
|
||||
private ClipboardHandler mClipboardHandler;
|
||||
public ClipManager mClipManager;
|
||||
public InputView mInputView;
|
||||
private int mCurrentCursorPosition;
|
||||
private Handler mHandler;
|
||||
private Cycler mSymbolCycler;
|
||||
private Vibrator mVibrator;
|
||||
public Vibrator mVibrator;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -59,7 +59,7 @@ public class InputMethod extends InputMethodService {
|
||||
mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
|
||||
mMetaKeyManager = new MetaKeyManager(mVibrator);
|
||||
mKeymapManager = new KeymapManager(this);
|
||||
mClipboardHandler = new ClipboardHandler(this);
|
||||
mClipManager = new ClipManager(this);
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mSymbolCycler = new SymbolCycler();
|
||||
mKeymapManager.cycleKeymaps(mPreferenceHolder.getSelectedKeymaps());
|
||||
@@ -166,6 +166,7 @@ public class InputMethod extends InputMethodService {
|
||||
@Override
|
||||
public void onFinishInput() {
|
||||
mMetaKeyManager.resetMetaKeyState();
|
||||
mInputView.mClipboardPopup.dismiss();
|
||||
}
|
||||
|
||||
// Cyclers
|
||||
|
||||
@@ -29,23 +29,30 @@ import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
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.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// TODO: programmatically scroll if current selected symbol is outside the visible space of the
|
||||
// scrollview
|
||||
|
||||
public class InputView extends RelativeLayout {
|
||||
protected final int[] BUTTON_STATE_TOGGLED = { R.attr.state_toggled };
|
||||
|
||||
private final InputMethod mInputMethod;
|
||||
private final LinearLayout.LayoutParams mSymbolLayout;
|
||||
private final LinearLayout.LayoutParams mCandidateLayout;
|
||||
private final LinearLayout.LayoutParams mClipLayout;
|
||||
private LinearLayout mSymbolList;
|
||||
private LinearLayout mClipsList;
|
||||
private LinearLayout mClipList;
|
||||
private Button mStateButton;
|
||||
private ImageButton mClipboardButton;
|
||||
private ScrollView mClipboardView;
|
||||
public PopupWindow mClipboardPopup;
|
||||
|
||||
public InputView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs, 0);
|
||||
@@ -53,18 +60,17 @@ public class InputView extends RelativeLayout {
|
||||
mSymbolLayout = new LinearLayout.LayoutParams(
|
||||
getResources().getDimensionPixelSize(R.dimen.symbol_width),
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0);
|
||||
mCandidateLayout = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0);
|
||||
mClipLayout = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, 0);
|
||||
|
||||
mSymbolLayout.setMargins(0, 0,
|
||||
getResources().getDimensionPixelSize(R.dimen.default_space), 0);
|
||||
mCandidateLayout.setMargins(0, 0,
|
||||
getResources().getDimensionPixelSize(R.dimen.default_space), 0);
|
||||
mClipLayout.setMargins(0,
|
||||
getResources().getDimensionPixelSize(R.dimen.default_space), 0, 0);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
mSymbolLayout.setMarginEnd(getResources().getDimensionPixelSize(R.dimen.default_space));
|
||||
mCandidateLayout.setMarginEnd(getResources().getDimensionPixelSize(R.dimen.default_space));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +78,14 @@ public class InputView extends RelativeLayout {
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSymbolList = findViewById(R.id.symbol_list);
|
||||
mClipsList = findViewById(R.id.clip_list);
|
||||
mStateButton = findViewById(R.id.state_button);
|
||||
mClipboardButton = findViewById(R.id.clipboard_button);
|
||||
mClipboardView = (ScrollView) inflate(this.getContext(), R.layout.clipboard, null);
|
||||
mClipList = mClipboardView.findViewById(R.id.clip_list);
|
||||
mClipboardPopup = new PopupWindow(mClipboardView,
|
||||
getResources().getDimensionPixelSize(R.dimen.clipboard_popup_width),
|
||||
getResources().getDimensionPixelSize(R.dimen.clipboard_popup_height), true);
|
||||
mClipboardPopup.setOnDismissListener(() -> mClipboardButton.setImageState(null, true));
|
||||
|
||||
mStateButton.setOnClickListener(button -> {
|
||||
MetaKeyManager metaManager = mInputMethod.mMetaKeyManager;
|
||||
@@ -89,6 +101,24 @@ public class InputView extends RelativeLayout {
|
||||
Intent intent = new Intent(getContext(), PreferenceActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
// For some reason, this vibrates by default, so we don't need to call the vibrator.
|
||||
return true;
|
||||
});
|
||||
|
||||
mClipboardButton.setOnClickListener(button -> {
|
||||
mClipboardPopup.showAsDropDown(mClipboardButton,
|
||||
-(mClipboardPopup.getWidth() - mClipboardButton.getWidth()) / 2, 0);
|
||||
mClipboardButton.setImageState(BUTTON_STATE_TOGGLED, true);
|
||||
});
|
||||
|
||||
mClipboardButton.setOnLongClickListener(button -> {
|
||||
// On a long click, we just send the latest clip (if any).
|
||||
if (!mInputMethod.mClipManager.isEmpty()
|
||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
mInputMethod.getCurrentInputConnection()
|
||||
.commitText(mInputMethod.mClipManager.get(0).getText(), 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -135,26 +165,33 @@ public class InputView extends RelativeLayout {
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void setClips(Object[] clips) {
|
||||
for (int i = 0; i < clips.length; ++i) {
|
||||
Button b = (Button) mClipsList.getChildAt(i);
|
||||
ClipData clip = (ClipData) clips[i];
|
||||
public void setClips(ArrayList<ClipData.Item> items) {
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
ClipData.Item item = items.get(i);
|
||||
LinearLayout clipView = (LinearLayout) mClipList.getChildAt(i);
|
||||
|
||||
if (b == null) {
|
||||
b = (Button) inflate(this.getContext(), R.layout.candidate, null);
|
||||
b.setTag(i);
|
||||
b.setLayoutParams(mCandidateLayout);
|
||||
mClipsList.addView(b);
|
||||
if (clipView == null) {
|
||||
clipView = (LinearLayout) inflate(this.getContext(), R.layout.clip, null);
|
||||
clipView.setTag(i);
|
||||
clipView.setLayoutParams(mClipLayout);
|
||||
mClipList.addView(clipView);
|
||||
}
|
||||
|
||||
ClipData.Item item = clip.getItemAt(0);
|
||||
b.setText(item.coerceToText(this.getContext()).toString());
|
||||
Button pasteButton = clipView.findViewById(R.id.paste_button);
|
||||
pasteButton.setText(item.getText());
|
||||
|
||||
pasteButton.setOnClickListener(button -> mInputMethod.getCurrentInputConnection().commitText(item.getText(), 1));
|
||||
|
||||
LinearLayout finalClipView = clipView;
|
||||
clipView.findViewById(R.id.button_delete).setOnClickListener(button -> {
|
||||
mClipList.removeView(finalClipView);
|
||||
mInputMethod.mClipManager.remove(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setSymbolsVisible(boolean state) {
|
||||
findViewById(R.id.symbol_list_container).setVisibility(state ? VISIBLE : GONE);
|
||||
findViewById(R.id.clip_list_container).setVisibility(state ? GONE : VISIBLE);
|
||||
mSymbolList.setVisibility(state ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
public void setSymbols(ArrayList<String> strings) {
|
||||
|
||||
@@ -17,17 +17,25 @@
|
||||
~
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item app:state_toggled="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/button_toggled" />
|
||||
<corners android:bottomLeftRadius="@dimen/default_border_radius"
|
||||
android:bottomRightRadius="@dimen/default_border_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#444" />
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="@color/button" />
|
||||
<corners android:radius="@dimen/default_border_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#666" />
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="@color/button_active" />
|
||||
<corners android:radius="@dimen/default_border_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/button_active" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -20,14 +20,16 @@
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#333" />
|
||||
<corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:radius="8dp" />
|
||||
<solid android:color="@color/candidate" />
|
||||
<corners android:topLeftRadius="@dimen/default_border_radius"
|
||||
android:topRightRadius="@dimen/default_border_radius"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#555" />
|
||||
<corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:radius="8dp" />
|
||||
<solid android:color="@color/candidate_active" />
|
||||
<corners android:topLeftRadius="@dimen/default_border_radius"
|
||||
android:topRightRadius="@dimen/default_border_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Main board -->
|
||||
<item>
|
||||
<inset android:insetTop="7.5%">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:color="@color/text_color" android:width="2dp" />
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<!-- The clip -->
|
||||
<item>
|
||||
<inset android:insetLeft="30%"
|
||||
android:insetRight="30%"
|
||||
android:insetBottom="80%">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/text_color"/>
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<!-- Squiggles -->
|
||||
<item>
|
||||
<inset android:insetBottom="25%"
|
||||
android:insetLeft="20%"
|
||||
android:insetRight="20%">
|
||||
<shape android:shape="line">
|
||||
<stroke android:width="2dp" android:color="@color/text_color" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<item>
|
||||
<inset
|
||||
android:insetTop="10%"
|
||||
android:insetLeft="20%"
|
||||
android:insetRight="20%">
|
||||
<shape android:shape="line">
|
||||
<stroke android:width="2dp" android:color="@color/text_color" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<item>
|
||||
<inset
|
||||
android:insetTop="45%"
|
||||
android:insetLeft="20%"
|
||||
android:insetRight="40%">
|
||||
<shape android:shape="line">
|
||||
<stroke android:width="2dp" android:color="@color/text_color" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -17,13 +17,8 @@
|
||||
~
|
||||
-->
|
||||
|
||||
<Button xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/InputViewCandidate"
|
||||
android:drawablePadding="@dimen/candidate_side_padding"
|
||||
android:ellipsize="end"
|
||||
android:maxWidth="@dimen/candidate_max_width"
|
||||
android:paddingLeft="@dimen/candidate_side_padding"
|
||||
android:paddingRight="@dimen/candidate_side_padding"
|
||||
android:singleLine="true">
|
||||
|
||||
</Button>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/button_toggled" />
|
||||
<corners android:radius="@dimen/default_border_radius" />
|
||||
</shape>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<inset android:insetTop="15%"
|
||||
android:insetLeft="10%"
|
||||
android:insetRight="10%">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp"
|
||||
android:color="@color/danger_text_color" />
|
||||
<corners android:bottomLeftRadius="4dp"
|
||||
android:bottomRightRadius="4dp"/>
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<item>
|
||||
<inset android:insetBottom="65%">
|
||||
<shape android:shape="line">
|
||||
<stroke android:width="2dp" android:color="@color/danger_text_color" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<item>
|
||||
<inset android:insetRight="30%"
|
||||
android:insetLeft="30%"
|
||||
android:insetBottom="75%">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp"
|
||||
android:color="@color/danger_text_color" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
<!-- Stripes -->
|
||||
<item>
|
||||
<inset android:insetTop="15%"
|
||||
android:insetLeft="35%"
|
||||
android:insetRight="35%">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp" android:color="@color/danger_text_color" />
|
||||
</shape>
|
||||
</inset>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="?android:listDivider">
|
||||
|
||||
<Button
|
||||
android:id="@+id/paste_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/button_transparent"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/default_space"
|
||||
android:singleLine="true"
|
||||
android:text="@string/clip_default_text"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/default_text_size" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_delete"
|
||||
android:layout_width="@dimen/button_size"
|
||||
android:layout_height="@dimen/button_size"
|
||||
android:background="@drawable/button_transparent"
|
||||
android:contentDescription="@string/delete_button_description"
|
||||
android:paddingLeft="@dimen/image_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/image_button_vertical_padding"
|
||||
android:paddingRight="@dimen/image_button_horizontal_padding"
|
||||
android:paddingBottom="@dimen/image_button_vertical_padding"
|
||||
android:src="@drawable/trashcan"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/popup"
|
||||
android:padding="@dimen/default_space">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/clip_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</ScrollView>
|
||||
@@ -18,10 +18,11 @@
|
||||
-->
|
||||
|
||||
<cfpi_fpsi.eu.titanboard.InputView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/InputViewBackground"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/background"
|
||||
android:paddingLeft="@dimen/default_space"
|
||||
android:paddingTop="@dimen/default_space"
|
||||
android:paddingRight="@dimen/default_space">
|
||||
@@ -30,13 +31,12 @@
|
||||
android:id="@+id/symbol_list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/container_height"
|
||||
android:layout_alignTop="@id/state_button"
|
||||
android:layout_alignTop="@id/clipboard_button"
|
||||
android:layout_marginEnd="@dimen/default_space"
|
||||
android:layout_marginRight="@dimen/default_space"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_toStartOf="@+id/state_button"
|
||||
android:layout_toLeftOf="@id/state_button"
|
||||
android:visibility="gone">
|
||||
android:layout_toStartOf="@+id/clipboard_button"
|
||||
android:layout_toLeftOf="@id/clipboard_button">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/symbol_list"
|
||||
@@ -47,32 +47,32 @@
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/clip_list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/container_height"
|
||||
android:layout_alignTop="@id/state_button"
|
||||
<ImageButton
|
||||
android:id="@+id/clipboard_button"
|
||||
android:layout_width="@dimen/button_size"
|
||||
android:layout_height="@dimen/button_size"
|
||||
android:layout_marginEnd="@dimen/default_space"
|
||||
android:layout_marginRight="@dimen/default_space"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_toStartOf="@+id/state_button"
|
||||
android:layout_toLeftOf="@id/state_button">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/clip_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal" />
|
||||
</HorizontalScrollView>
|
||||
android:layout_toStartOf="@id/state_button"
|
||||
android:layout_toLeftOf="@id/state_button"
|
||||
android:background="@drawable/button"
|
||||
android:contentDescription="@string/clipboard_button_description"
|
||||
android:paddingLeft="@dimen/image_button_horizontal_padding"
|
||||
android:paddingTop="@dimen/image_button_vertical_padding"
|
||||
android:paddingRight="@dimen/image_button_horizontal_padding"
|
||||
android:paddingBottom="@dimen/image_button_vertical_padding"
|
||||
android:src="@drawable/clipboard"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/state_button"
|
||||
style="@style/InputViewButton"
|
||||
android:layout_width="@dimen/button_width"
|
||||
android:layout_height="@dimen/button_height"
|
||||
android:layout_width="@dimen/button_size"
|
||||
android:layout_height="@dimen/button_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="@drawable/button"
|
||||
android:text="@string/state_button_default"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/default_text_size" />
|
||||
|
||||
</cfpi_fpsi.eu.titanboard.InputView>
|
||||
@@ -18,8 +18,11 @@
|
||||
-->
|
||||
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/InputViewCandidate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/candidate"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/default_text_size">
|
||||
|
||||
</TextView>
|
||||
@@ -18,18 +18,5 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="InputViewBackground">
|
||||
<item name="android:background">#222</item>
|
||||
</style>
|
||||
|
||||
<style name="InputViewButton">
|
||||
<item name="android:background">@drawable/button</item>
|
||||
<item name="android:textColor">#FFF</item>
|
||||
</style>
|
||||
|
||||
<style name="InputViewCandidate">
|
||||
<item name="android:background">@drawable/candidate</item>
|
||||
<item name="android:textColor">#FFF</item>
|
||||
</style>
|
||||
<attr name="state_toggled" format="boolean" />
|
||||
</resources>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ An input method for the Unihertz Titan/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 <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="background">#222</color>
|
||||
<color name="button">#444</color>
|
||||
<color name="button_toggled">#555</color>
|
||||
<color name="button_active">#666</color>
|
||||
<color name="candidate">#333</color>
|
||||
<color name="candidate_active">#666</color>
|
||||
<color name="text_color">#EEE</color>
|
||||
<color name="danger_text_color">#FF0000</color>
|
||||
</resources>
|
||||
@@ -20,10 +20,12 @@
|
||||
<resources>
|
||||
<dimen name="default_space">8dp</dimen>
|
||||
<dimen name="container_height">56dp</dimen>
|
||||
<dimen name="button_width">48dp</dimen>
|
||||
<dimen name="button_height">48dp</dimen>
|
||||
<dimen name="candidate_max_width">196dp</dimen>
|
||||
<dimen name="candidate_side_padding">12dp</dimen>
|
||||
<dimen name="button_size">48dp</dimen>
|
||||
<dimen name="symbol_width">40dp</dimen>
|
||||
<dimen name="default_text_size">18sp</dimen>
|
||||
<dimen name="default_text_size">16sp</dimen>
|
||||
<dimen name="image_button_vertical_padding">12dp</dimen>
|
||||
<dimen name="image_button_horizontal_padding">14dp</dimen>
|
||||
<dimen name="clipboard_popup_width">196dp</dimen>
|
||||
<dimen name="clipboard_popup_height">256dp</dimen>
|
||||
<dimen name="default_border_radius">8dp</dimen>
|
||||
</resources>
|
||||
@@ -2,10 +2,18 @@
|
||||
<string name="app_name">Titanboard</string>
|
||||
<string name="preferences_name">Titanboard preferences</string>
|
||||
|
||||
<string name="keymap_default">en</string>
|
||||
<string name="cycle_speed_default">500</string>
|
||||
<string name="clipboard_max_items_default">10</string>
|
||||
|
||||
<string name="state_button_default">\??</string>
|
||||
<string name="state_button_alt_locked">#!</string>
|
||||
<string name="state_button_alt_latched">#?</string>
|
||||
|
||||
<string name="delete_button_description">Delete clipboard item</string>
|
||||
<string name="clipboard_button_description">Open clipboard or paste first item on long press</string>
|
||||
<string name="clip_default_text">Clip</string>
|
||||
|
||||
<string name="preferences_label_floating_interface">Floating interface</string>
|
||||
<string name="preferences_label_cycle_speed">Cycling speed</string>
|
||||
<string name="preferences_label_clipboard_max_items">Maximum clipboard items</string>
|
||||
@@ -24,8 +32,4 @@
|
||||
<string name="preferences_key_keymaps">selected_keymaps</string>
|
||||
<string name="preferences_key_cycle_speed">cycle_speed</string>
|
||||
<string name="preferences_key_clipboard_max_items">clipboard_items</string>
|
||||
|
||||
<string name="keymap_default">en</string>
|
||||
<string name="cycle_speed_default">500</string>
|
||||
<string name="clipboard_max_items_default">10</string>
|
||||
</resources>
|
||||
@@ -21,6 +21,7 @@
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="@bool/floating_ui_default"
|
||||
android:enabled="false"
|
||||
android:key="@string/preferences_key_floating_interface"
|
||||
android:summary="@string/preferences_summary_floating_interface"
|
||||
android:title="@string/preferences_label_floating_interface" />
|
||||
|
||||
Reference in New Issue
Block a user