Repository navigation
fix code review suggestions #240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -191,6 +191,11 @@ private static final class SaveRequest { | |
|
|
||
| WebView mWebView; | ||
|
|
||
| private int cachedMaxHorizontalScroll = 0; | ||
| private int cachedHorizontalScrollEditorWidth = -1; | ||
| private boolean horizontalScrollBoundsDirty = true; | ||
| private int horizontalScrollBoundsCalculationCount = 0; | ||
|
|
||
| /** | ||
| * Called when the activity is first created. | ||
| */ | ||
|
|
@@ -218,6 +223,13 @@ public void onCreate(Bundle savedInstanceState) { | |
| mText = this.findViewById(R.id.editText1); | ||
| mText.setBackgroundResource(android.R.color.transparent); | ||
| mText.setOnTouchListener(new TwoFingerPanTouchListener()); | ||
| mText.addOnLayoutChangeListener((view, left, top, right, bottom, | ||
| oldLeft, oldTop, oldRight, oldBottom) -> { | ||
| if ((right - left) != (oldRight - oldLeft) | ||
| || (bottom - top) != (oldBottom - oldTop)) { | ||
| invalidateHorizontalScrollBounds(); | ||
| } | ||
| }); | ||
| editTextUndoRedo = new EditTextUndoRedo(mText, this); | ||
| setTextWatcher(); | ||
|
|
||
|
|
@@ -339,6 +351,7 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { | |
|
|
||
| @Override | ||
| public void onTextChanged(CharSequence s, int start, int before, int count) { | ||
| invalidateHorizontalScrollBounds(); | ||
| if (suppressRecoveryTracking) { | ||
| return; | ||
| } | ||
|
|
@@ -760,12 +773,14 @@ private boolean isFilenameEmpty() { | |
| } | ||
|
|
||
| void applyPreferences() { | ||
| invalidateHorizontalScrollBounds(); | ||
| applyFontFace(); | ||
| applyFontSize(); | ||
| applyColors(); | ||
| } | ||
|
|
||
| private void disableEditorAutowrapping() { | ||
| invalidateHorizontalScrollBounds(); | ||
| mText.setHorizontallyScrolling(true); | ||
| mText.setHorizontalScrollBarEnabled(true); | ||
| mText.setMaxLines(Integer.MAX_VALUE); | ||
|
|
@@ -1975,6 +1990,7 @@ protected void showToast(String toast_str) { | |
| private class TwoFingerPanTouchListener implements View.OnTouchListener { | ||
|
|
||
| private boolean panningActive = false; | ||
| private boolean panGestureOwned = false; | ||
| private float lastFocalX; | ||
| private float lastFocalY; | ||
| private int maxScrollX; | ||
|
|
@@ -1984,21 +2000,25 @@ private class TwoFingerPanTouchListener implements View.OnTouchListener { | |
| public boolean onTouch(View view, MotionEvent event) { | ||
| switch (event.getActionMasked()) { | ||
| case MotionEvent.ACTION_DOWN: | ||
| stopPanning(view); | ||
| endPanGesture(view); | ||
| return false; | ||
| case MotionEvent.ACTION_POINTER_DOWN: | ||
| if (event.getPointerCount() == 2) { | ||
| startPanning(view, event); | ||
| } else { | ||
| return stopPanning(view); | ||
| stopActivePanning(view); | ||
| } | ||
| return panningActive; | ||
| return panGestureOwned; | ||
| case MotionEvent.ACTION_MOVE: | ||
| if (!panningActive) { | ||
| if (!panGestureOwned) { | ||
| return false; | ||
| } | ||
| if (!panningActive) { | ||
| return true; | ||
| } | ||
| if (event.getPointerCount() != 2) { | ||
| return stopPanning(view); | ||
| stopActivePanning(view); | ||
| return true; | ||
| } | ||
| float focalX = focalX(event); | ||
| float focalY = focalY(event); | ||
|
|
@@ -2012,32 +2032,42 @@ public boolean onTouch(View view, MotionEvent event) { | |
| lastFocalY = focalY; | ||
| return true; | ||
| case MotionEvent.ACTION_POINTER_UP: | ||
| return stopPanning(view); | ||
| if (panGestureOwned) { | ||
| stopActivePanning(view); | ||
| return true; | ||
| } | ||
| return false; | ||
| case MotionEvent.ACTION_UP: | ||
| case MotionEvent.ACTION_CANCEL: | ||
| return stopPanning(view); | ||
| return endPanGesture(view); | ||
| default: | ||
| return panningActive; | ||
| return panGestureOwned; | ||
| } | ||
| } | ||
|
|
||
| private void startPanning(View view, MotionEvent event) { | ||
| panningActive = true; | ||
| panGestureOwned = true; | ||
| requestParentInterception(view, true); | ||
| lastFocalX = focalX(event); | ||
| lastFocalY = focalY(event); | ||
| Layout layout = mText.getLayout(); | ||
| maxScrollX = calculateMaxHorizontalScroll(layout); | ||
| maxScrollX = getMaxHorizontalScroll(layout); | ||
| maxScrollY = calculateMaxVerticalScroll(layout); | ||
| } | ||
|
|
||
| private boolean stopPanning(View view) { | ||
| boolean wasPanning = panningActive; | ||
| panningActive = false; | ||
| if (wasPanning) { | ||
| private void stopActivePanning(View view) { | ||
| if (panningActive) { | ||
| requestParentInterception(view, false); | ||
| } | ||
| return wasPanning; | ||
| panningActive = false; | ||
| } | ||
|
|
||
| private boolean endPanGesture(View view) { | ||
| boolean shouldConsume = panGestureOwned || panningActive; | ||
| stopActivePanning(view); | ||
| panGestureOwned = false; | ||
| return shouldConsume; | ||
| } | ||
|
|
||
| private void requestParentInterception(View view, boolean disallow) { | ||
|
|
@@ -2079,17 +2109,36 @@ private void panContent(int deltaX, int deltaY, int maxScrollX, int maxScrollY) | |
| mText.scrollTo(newX, mText.getScrollY()); | ||
| } | ||
|
|
||
| private int calculateMaxHorizontalScroll(Layout layout) { | ||
| if (layout == null) { | ||
| private int getMaxHorizontalScroll(Layout layout) { | ||
| int editorWidth = mText.getWidth(); | ||
| if (layout == null || editorWidth <= 0) { | ||
| return 0; | ||
| } | ||
| if (horizontalScrollBoundsDirty || cachedHorizontalScrollEditorWidth != editorWidth) { | ||
| cachedMaxHorizontalScroll = calculateMaxHorizontalScroll(layout, editorWidth); | ||
| cachedHorizontalScrollEditorWidth = editorWidth; | ||
| horizontalScrollBoundsDirty = false; | ||
|
Comment on lines
+2117
to
+2120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an unchanged open document is modified externally while the activity is paused, Useful? React with 👍 / 👎. |
||
| } | ||
| return cachedMaxHorizontalScroll; | ||
| } | ||
|
|
||
| private void invalidateHorizontalScrollBounds() { | ||
| horizontalScrollBoundsDirty = true; | ||
| } | ||
|
|
||
| public int getHorizontalScrollBoundsCalculationCountForTests() { | ||
| return horizontalScrollBoundsCalculationCount; | ||
| } | ||
|
|
||
| private int calculateMaxHorizontalScroll(Layout layout, int editorWidth) { | ||
| horizontalScrollBoundsCalculationCount++; | ||
| float maxLineWidth = 0; | ||
| for (int line = 0; line < layout.getLineCount(); line++) { | ||
| maxLineWidth = Math.max(maxLineWidth, layout.getLineWidth(line)); | ||
| } | ||
| int contentWidth = (int) Math.ceil(maxLineWidth) | ||
| + mText.getTotalPaddingLeft() + mText.getTotalPaddingRight(); | ||
| return Math.max(0, contentWidth - mText.getWidth()); | ||
| return Math.max(0, contentWidth - editorWidth); | ||
| } | ||
|
|
||
| private int calculateMaxVerticalScroll(Layout layout) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the second finger makes the listener own the gesture,
EditText.onTouchEventhas already received the initialACTION_DOWN, but this listener now consumes every remaining event, including the finalACTION_UPorACTION_CANCEL. The editor therefore never clears its pending tap/long-press and pressed state, so a quick two-finger pan can trigger a delayed long-click or selection at the first touch location after both fingers are released. Send the editor a cancellation event when taking ownership before swallowing the rest of the stream.Useful? React with 👍 / 👎.