DroidFish: Speeded up move list drawing by reducing the number of span

objects.
This commit is contained in:
Peter Osterlund
2015-12-31 00:47:26 +01:00
parent 39607ff9a4
commit b1a3eee254
2 changed files with 42 additions and 33 deletions

View File

@@ -107,10 +107,8 @@ import android.text.Html;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.LeadingMarginSpan; import android.text.style.LeadingMarginSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
@@ -425,6 +423,7 @@ public class DroidFish extends Activity implements GUIInterface {
initUI(); initUI();
gameTextListener = new PgnScreenText(this, pgnOptions); gameTextListener = new PgnScreenText(this, pgnOptions);
moveList.setOnLinkClickListener(gameTextListener);
if (ctrl != null) if (ctrl != null)
ctrl.shutdownEngine(); ctrl.shutdownEngine();
ctrl = new DroidChessController(this, gameTextListener, pgnOptions); ctrl = new DroidChessController(this, gameTextListener, pgnOptions);
@@ -616,6 +615,7 @@ public class DroidFish extends Activity implements GUIInterface {
setSelection(oldCB.selectedSquare); setSelection(oldCB.selectedSquare);
cb.userSelectedSquare = oldCB.userSelectedSquare; cb.userSelectedSquare = oldCB.userSelectedSquare;
setStatusString(statusStr); setStatusString(statusStr);
moveList.setOnLinkClickListener(gameTextListener);
moveListUpdated(); moveListUpdated();
updateThinkingInfo(); updateThinkingInfo();
ctrl.updateRemainingTime(); ctrl.updateRemainingTime();
@@ -3526,8 +3526,10 @@ public class DroidFish extends Activity implements GUIInterface {
} }
/** PngTokenReceiver implementation that renders PGN data for screen display. */ /** PngTokenReceiver implementation that renders PGN data for screen display. */
static class PgnScreenText implements PgnToken.PgnTokenReceiver { static class PgnScreenText implements PgnToken.PgnTokenReceiver,
MoveListView.OnLinkClickListener {
private SpannableStringBuilder sb = new SpannableStringBuilder(); private SpannableStringBuilder sb = new SpannableStringBuilder();
private TreeMap<Integer,Node> offs2Node = new TreeMap<Integer,Node>();
private int prevType = PgnToken.EOF; private int prevType = PgnToken.EOF;
int nestLevel = 0; int nestLevel = 0;
boolean col0 = true; boolean col0 = true;
@@ -3592,28 +3594,31 @@ public class DroidFish extends Activity implements GUIInterface {
boolean pendingNewLine = false; boolean pendingNewLine = false;
/** Makes moves in the move list clickable. */ private void addMoveLink(Node node, int l0, int l1) {
private final class MoveLink extends ClickableSpan { offs2Node.put(l0, node);
private Node node; offs2Node.put(l1, null);
MoveLink(Node n) { }
node = n;
} @Override
@Override public boolean onLinkClick(int offs) {
public void onClick(View widget) { if (ctrl == null)
if (ctrl != null) { return false;
// On android 4.1 this onClick method is called Map.Entry<Integer, Node> e = offs2Node.floorEntry(offs);
// even when you long click the move list. The test if (e == null)
// below works around the problem. return false;
Dialog mlmd = moveListMenuDlg; Node node = e.getValue();
if ((mlmd == null) || !mlmd.isShowing()) { if (node == null)
df.setAutoMode(AutoMode.OFF); return false;
ctrl.goNode(node);
} // On android 4.1 this onClick method is called
} // even when you long click the move list. The test
} // below works around the problem.
@Override Dialog mlmd = moveListMenuDlg;
public void updateDrawState(TextPaint ds) { if ((mlmd == null) || !mlmd.isShowing()) {
df.setAutoMode(AutoMode.OFF);
ctrl.goNode(node);
} }
return true;
} }
public void processToken(Node node, int type, String token) { public void processToken(Node node, int type, String token) {
@@ -3677,7 +3682,7 @@ public class DroidFish extends Activity implements GUIInterface {
sb.append(token); sb.append(token);
int l1 = sb.length(); int l1 = sb.length();
nodeToCharPos.put(node, new NodeInfo(l0, l1)); nodeToCharPos.put(node, new NodeInfo(l0, l1));
sb.setSpan(new MoveLink(node), l0, l1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); addMoveLink(node, l0, l1);
if (endPos < l0) endPos = l0; if (endPos < l0) endPos = l0;
col0 = false; col0 = false;
if (nestLevel == 0) paraBold = true; if (nestLevel == 0) paraBold = true;
@@ -3714,6 +3719,7 @@ public class DroidFish extends Activity implements GUIInterface {
@Override @Override
public void clear() { public void clear() {
sb = new SpannableStringBuilder(); sb = new SpannableStringBuilder();
offs2Node.clear();
prevType = PgnToken.EOF; prevType = PgnToken.EOF;
nestLevel = 0; nestLevel = 0;
col0 = true; col0 = true;

View File

@@ -25,10 +25,8 @@ import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.text.Layout; import android.text.Layout;
import android.text.Layout.Alignment; import android.text.Layout.Alignment;
import android.text.Spannable;
import android.text.StaticLayout; import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.MotionEvent; import android.view.MotionEvent;
@@ -154,23 +152,28 @@ public class MoveListView extends View {
} }
} }
public interface OnLinkClickListener {
boolean onLinkClick(int offs);
}
private OnLinkClickListener onLinkClickListener;
public void setOnLinkClickListener(OnLinkClickListener listener) {
onLinkClickListener = listener;
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked(); int action = event.getActionMasked();
boolean ret = super.onTouchEvent(event); boolean ret = super.onTouchEvent(event);
if ((action == MotionEvent.ACTION_UP) && (layout != null) && if ((action == MotionEvent.ACTION_UP) && (layout != null) &&
(text instanceof Spannable)) { (onLinkClickListener != null)) {
Spannable spannable = (Spannable)text;
int x = (int)event.getX() - getPaddingLeft() + getScrollX(); int x = (int)event.getX() - getPaddingLeft() + getScrollX();
int y = (int)event.getY() - getPaddingTop() + getScrollY(); int y = (int)event.getY() - getPaddingTop() + getScrollY();
int line = layout.getLineForVertical(y); int line = layout.getLineForVertical(y);
int offs = layout.getOffsetForHorizontal(line, x); int offs = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = spannable.getSpans(offs, offs, ClickableSpan.class); if (onLinkClickListener.onLinkClick(offs))
if (link.length > 0) {
link[0].onClick(this);
return true; return true;
}
} }
return ret; return ret;
} }