submodule vendor/libswipetype now points to http://10.0.1.49:3010/harley/libswipetype.git (commit e4aef2f) instead of upstream github.com/libswipetype/libswipetype. Key change: removed [0,1] bounding-box normalization from both PathProcessor and IdealPathGenerator. Paths now stay in original dp coordinates so DTW measures actual keyboard distance between keys.
141 lines
4.3 KiB
Java
141 lines
4.3 KiB
Java
package juloo.keyboard2;
|
|
|
|
import android.content.Context;
|
|
import android.util.Log;
|
|
import java.io.InputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import dev.dettmer.swipetype.android.GesturePoint;
|
|
import dev.dettmer.swipetype.android.KeyboardLayoutDescriptor;
|
|
import dev.dettmer.swipetype.android.KeyboardLayoutDescriptor.KeyInfo;
|
|
import dev.dettmer.swipetype.android.SwipeTypeAdapter;
|
|
import dev.dettmer.swipetype.android.SwipeTypeCandidate;
|
|
import dev.dettmer.swipetype.android.SwipeTypeEngine;
|
|
import dev.dettmer.swipetype.android.SwipeTypeError;
|
|
|
|
public class UnexpectedKeyboardSwipeAdapter implements SwipeTypeAdapter
|
|
{
|
|
private static final String TAG = "SwipeAdapter";
|
|
|
|
private SwipeTypeEngine _engine;
|
|
private Context _context;
|
|
|
|
private List<GesturePoint> _gesturePoints = new ArrayList<>();
|
|
private boolean _gestureActive = false;
|
|
private CandidatesCallback _candidatesCallback;
|
|
|
|
/** Key positions (dp) set by the view after layout. */
|
|
private List<KeyInfo> _cachedKeys = null;
|
|
private float _layoutWidthDp = 0;
|
|
private float _layoutHeightDp = 0;
|
|
|
|
public interface CandidatesCallback
|
|
{
|
|
void onSwipeCandidates(String[] words, float[] scores);
|
|
}
|
|
|
|
public UnexpectedKeyboardSwipeAdapter(Context context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
/** Called by the view after layout with all key positions in dp. */
|
|
public void setKeyLayout(List<KeyInfo> keys, float widthDp, float heightDp)
|
|
{
|
|
_cachedKeys = keys;
|
|
_layoutWidthDp = widthDp;
|
|
_layoutHeightDp = heightDp;
|
|
if (_engine != null && _engine.isInitialized())
|
|
_engine.notifyLayoutChanged();
|
|
}
|
|
|
|
public void init(CandidatesCallback callback)
|
|
{
|
|
_candidatesCallback = callback;
|
|
_engine = new SwipeTypeEngine();
|
|
_engine.init(_context, this);
|
|
loadDict();
|
|
}
|
|
|
|
private void loadDict()
|
|
{
|
|
int resId = _context.getResources().getIdentifier(
|
|
"en_us_sample", "raw", _context.getPackageName());
|
|
if (resId == 0) { Log.w(TAG, "Dictionary resource not found"); return; }
|
|
try (InputStream is = _context.getResources().openRawResource(resId))
|
|
{
|
|
boolean ok = _engine.loadDictionary("en-US", is);
|
|
Log.i(TAG, "loadDictionary: " + ok);
|
|
}
|
|
catch (Exception e) { Log.e(TAG, "Failed: " + e.getMessage()); }
|
|
}
|
|
|
|
public void startGesture() { _gesturePoints.clear(); _gestureActive = true; }
|
|
|
|
public void addPoint(float x, float y, long timestamp)
|
|
{
|
|
if (_gestureActive) _gesturePoints.add(new GesturePoint(x, y, timestamp));
|
|
}
|
|
|
|
public void finishGesture()
|
|
{
|
|
_gestureActive = false;
|
|
if (_gesturePoints.size() < 3) { _gesturePoints.clear(); return; }
|
|
_engine.processGesture(_gesturePoints);
|
|
_gesturePoints.clear();
|
|
}
|
|
|
|
public void cancelGesture() { _gestureActive = false; _gesturePoints.clear(); }
|
|
|
|
// ===== SwipeTypeAdapter =====
|
|
|
|
@Override
|
|
public void onInit(SwipeTypeEngine engine) { Log.i(TAG, "Engine initialized"); }
|
|
|
|
@Override
|
|
public KeyboardLayoutDescriptor getKeyboardLayout()
|
|
{
|
|
if (_cachedKeys != null && !_cachedKeys.isEmpty())
|
|
return new KeyboardLayoutDescriptor("en-US", _cachedKeys,
|
|
_layoutWidthDp, _layoutHeightDp);
|
|
// Fallback — should not be reached once the view reports layout
|
|
List<KeyInfo> stub = new ArrayList<>();
|
|
float d = _context.getResources().getDisplayMetrics().density;
|
|
String[] rows = {"qwertyuiop", "asdfghjkl", "zxcvbnm"};
|
|
float y = 0;
|
|
for (String r : rows) {
|
|
float x = 0;
|
|
for (int i = 0; i < r.length(); i++) {
|
|
char c = r.charAt(i);
|
|
stub.add(new KeyInfo(String.valueOf(c), (int)c, x+12f/d, y+12f/d, 24f/d, 24f/d));
|
|
x += 24f/d;
|
|
}
|
|
y += 24f/d;
|
|
}
|
|
return new KeyboardLayoutDescriptor("en-US", stub, 240f/d, 72f/d);
|
|
}
|
|
|
|
@Override
|
|
public void onCandidatesReady(List<SwipeTypeCandidate> candidates)
|
|
{
|
|
if (_candidatesCallback == null || candidates.isEmpty()) return;
|
|
String[] words = new String[candidates.size()];
|
|
float[] scores = new float[candidates.size()];
|
|
for (int i = 0; i < candidates.size(); i++)
|
|
{
|
|
words[i] = candidates.get(i).word;
|
|
scores[i] = candidates.get(i).confidence;
|
|
}
|
|
_candidatesCallback.onSwipeCandidates(words, scores);
|
|
}
|
|
|
|
@Override
|
|
public void onError(SwipeTypeError error) { Log.e(TAG, "Error: " + error.name()); }
|
|
|
|
public void shutdown()
|
|
{
|
|
if (_engine != null) _engine.shutdown();
|
|
}
|
|
}
|