Loading src/com/android/documentsui/inspector/HeaderTextSelector.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui.inspector; import static com.android.internal.util.Preconditions.checkArgument; import android.text.Spannable; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; /** * Selects all or part of a textview. */ public final class HeaderTextSelector implements ActionMode.Callback { private final TextView mText; private final Selector mSelector; public HeaderTextSelector(TextView text, Selector selector) { checkArgument(text != null); checkArgument(selector != null); mText = text; mSelector = selector; } // An action mode is created when the user selects text. This method is called where // we force it to select only the filename in the header. Meaning the name of the file would // be selected but the extension would not. @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { CharSequence value = mText.getText(); if (value instanceof Spannable) { mSelector.select((Spannable) value, 0, getLengthOfFilename(value)); } return true; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return true; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; } @Override public void onDestroyActionMode(ActionMode actionMode) {} /** * Gets the length of the inspector header for selection. * * Example: * filename.txt returns the end index needed to select "filename". * * @return the index of the last character in the filename */ private static int getLengthOfFilename(CharSequence text) { String title = text.toString(); if (title != null) { int index = title.indexOf('.'); if (index > 0) { return index; } } return text.length(); } public interface Selector { void select(Spannable text, int start, int stop); } } src/com/android/documentsui/inspector/HeaderView.java +8 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.drawable.Drawable; import android.text.Selection; import android.text.Spannable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; Loading Loading @@ -77,6 +79,12 @@ public final class HeaderView extends RelativeLayout implements HeaderDisplay { public void accept(DocumentInfo info, String displayName) { loadHeaderImage(info); mTitle.setText(displayName); mTitle.setCustomSelectionActionModeCallback( new HeaderTextSelector(mTitle, this::selectText)); } private void selectText(Spannable text, int start, int stop) { Selection.setSelection(text, start, stop); } private void loadHeaderImage(DocumentInfo doc) { Loading tests/unit/com/android/documentsui/inspector/HeaderTextSelectorTest.java 0 → 100644 +136 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui.inspector; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.text.Spannable; import android.text.SpannableString; import android.widget.TextView; import com.android.documentsui.inspector.HeaderTextSelector.Selector; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class HeaderTextSelectorTest { private Context mContext; private TestTextView mTestTextView; private TestSelector mTestSelector; private HeaderTextSelector mSelector; @Before public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mTestTextView = new TestTextView(mContext); mTestSelector = new TestSelector(); mSelector = new HeaderTextSelector(mTestTextView, mTestSelector); } @Test public void testSimpleFileName() throws Exception { CharSequence fileName = "filename"; String extension = ".txt"; String testSequence = fileName + extension; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, fileName); } @Test public void testLotsOfPeriodsInFileName() throws Exception { CharSequence fileName = "filename"; String extension = ".jpg.zip.pdf.txt"; String testSequence = fileName + extension; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, fileName); } @Test public void testNoPeriodsInFileName() throws Exception { String testSequence = "filename"; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, testSequence); } private static class TestTextView extends TextView { public TestTextView(Context context) { super(context); } private String textViewString; public void setText(String text) { textViewString = text; } @Override public CharSequence getText() { return new SpannableString(textViewString); } } private static class TestSelector implements Selector { private boolean mCalled; private int mStart; private int mStop; public TestSelector() { mCalled = false; mStart = -1; mStop = -1; } @Override public void select(Spannable text, int start, int stop) { mCalled = true; mStart = start; mStop = stop; } public void assertCalled() { assertTrue(mCalled); } } } No newline at end of file Loading
src/com/android/documentsui/inspector/HeaderTextSelector.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui.inspector; import static com.android.internal.util.Preconditions.checkArgument; import android.text.Spannable; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; /** * Selects all or part of a textview. */ public final class HeaderTextSelector implements ActionMode.Callback { private final TextView mText; private final Selector mSelector; public HeaderTextSelector(TextView text, Selector selector) { checkArgument(text != null); checkArgument(selector != null); mText = text; mSelector = selector; } // An action mode is created when the user selects text. This method is called where // we force it to select only the filename in the header. Meaning the name of the file would // be selected but the extension would not. @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { CharSequence value = mText.getText(); if (value instanceof Spannable) { mSelector.select((Spannable) value, 0, getLengthOfFilename(value)); } return true; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return true; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return false; } @Override public void onDestroyActionMode(ActionMode actionMode) {} /** * Gets the length of the inspector header for selection. * * Example: * filename.txt returns the end index needed to select "filename". * * @return the index of the last character in the filename */ private static int getLengthOfFilename(CharSequence text) { String title = text.toString(); if (title != null) { int index = title.indexOf('.'); if (index > 0) { return index; } } return text.length(); } public interface Selector { void select(Spannable text, int start, int stop); } }
src/com/android/documentsui/inspector/HeaderView.java +8 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.drawable.Drawable; import android.text.Selection; import android.text.Spannable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; Loading Loading @@ -77,6 +79,12 @@ public final class HeaderView extends RelativeLayout implements HeaderDisplay { public void accept(DocumentInfo info, String displayName) { loadHeaderImage(info); mTitle.setText(displayName); mTitle.setCustomSelectionActionModeCallback( new HeaderTextSelector(mTitle, this::selectText)); } private void selectText(Spannable text, int start, int stop) { Selection.setSelection(text, start, stop); } private void loadHeaderImage(DocumentInfo doc) { Loading
tests/unit/com/android/documentsui/inspector/HeaderTextSelectorTest.java 0 → 100644 +136 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui.inspector; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.text.Spannable; import android.text.SpannableString; import android.widget.TextView; import com.android.documentsui.inspector.HeaderTextSelector.Selector; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class HeaderTextSelectorTest { private Context mContext; private TestTextView mTestTextView; private TestSelector mTestSelector; private HeaderTextSelector mSelector; @Before public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mTestTextView = new TestTextView(mContext); mTestSelector = new TestSelector(); mSelector = new HeaderTextSelector(mTestTextView, mTestSelector); } @Test public void testSimpleFileName() throws Exception { CharSequence fileName = "filename"; String extension = ".txt"; String testSequence = fileName + extension; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, fileName); } @Test public void testLotsOfPeriodsInFileName() throws Exception { CharSequence fileName = "filename"; String extension = ".jpg.zip.pdf.txt"; String testSequence = fileName + extension; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, fileName); } @Test public void testNoPeriodsInFileName() throws Exception { String testSequence = "filename"; mTestTextView.setText(testSequence); mSelector.onCreateActionMode(null, null); mTestSelector.assertCalled(); CharSequence selectedSequence = testSequence.subSequence(mTestSelector.mStart, mTestSelector.mStop); assertEquals(selectedSequence, testSequence); } private static class TestTextView extends TextView { public TestTextView(Context context) { super(context); } private String textViewString; public void setText(String text) { textViewString = text; } @Override public CharSequence getText() { return new SpannableString(textViewString); } } private static class TestSelector implements Selector { private boolean mCalled; private int mStart; private int mStop; public TestSelector() { mCalled = false; mStart = -1; mStop = -1; } @Override public void select(Spannable text, int start, int stop) { mCalled = true; mStart = start; mStop = stop; } public void assertCalled() { assertTrue(mCalled); } } } No newline at end of file