package net.nightwhistler.pageturner.view.bookview; import android.text.Spanned; import android.text.SpannedString; import android.text.StaticLayout; import org.junit.Assert; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class LayoutTextUtil { /** * Very simple Layout class with predictable properties. * * It ignores all formatting, creating fixed-length lines. * * @author Alex Kuiper * */ private static class SimpleLayout { private CharSequence text; private int lineWidth; private int lineHeight; public SimpleLayout(CharSequence text, int lineWidth, int lineHeight) { this.text = text; this.lineWidth = lineWidth; this.lineHeight = lineHeight; } public int getLineCount() { return (text.length() / lineWidth) + 1; } public int getHeight() { return getLineCount() * lineHeight; } public int getLineForVertical(int vertical) { int line = vertical / lineHeight; int lastLine = text.length() / lineWidth; if ( line < 0 ) { return 0; } else if ( line > lastLine ) { return lastLine; } return line; } public int getLineStart(int line) { if ( line >= getLineCount() ) { return text.length(); } return line * lineWidth; } public int getLineEnd(int line) { return getLineStart(line + 1); } public int getLineTop( int line ) { return line * lineHeight; } public int getLineForOffset( int offset ) { return offset / lineWidth; } } /** * Returns a StaticLayout which delegates most work to a SimpleLayout. * * @param text the text to layout * @param lineWidth the number of characters in a line * @param lineHeight height of a line in pixels * @return a mocked StaticLayout */ public static StaticLayout createMockLayout( final CharSequence text, final int lineWidth, final int lineHeight ) { final StaticLayout mockLayout = mock(StaticLayout.class); final SimpleLayout simpleLayout = new SimpleLayout(text, lineWidth, lineHeight); when( mockLayout.getLineCount() ).thenReturn( simpleLayout.getLineCount() ); when( mockLayout.getHeight() ).thenReturn( simpleLayout.getHeight() ); when( mockLayout.getLineForVertical(anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { Integer vertical = (Integer) invocation.getArguments()[0]; return simpleLayout.getLineForVertical(vertical); } }); when( mockLayout.getLineStart(anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { Integer line = (Integer) invocation.getArguments()[0]; return simpleLayout.getLineStart(line); } }); when( mockLayout.getLineEnd(anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { int line = (Integer) invocation.getArguments()[0]; return simpleLayout.getLineEnd(line); } }); when( mockLayout.getLineForOffset(anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { int offset = (Integer) invocation.getArguments()[0]; return simpleLayout.getLineForOffset(offset); } }); when( mockLayout.getLineTop(anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { int line = (Integer) invocation.getArguments()[0]; return simpleLayout.getLineTop(line); } }); return mockLayout; } public static Spanned getSpanned( final String fromString ) { Spanned mockSpanned = Mockito.spy(new SpannedString(fromString)); when(mockSpanned.subSequence(anyInt(), anyInt())).thenAnswer(new Answer<CharSequence>() { @Override public CharSequence answer(InvocationOnMock invocation) throws Throwable { return fromString.subSequence( (Integer) invocation.getArguments()[0], (Integer) invocation.getArguments()[1]); } }); when(mockSpanned.length()).thenReturn(fromString.length()); when(mockSpanned.toString()).thenReturn(fromString); return mockSpanned; } public static String getStringOfLength( String seed, int length ) { StringBuilder builder = new StringBuilder(); int repeat = length / seed.length(); for ( int i=0; i < repeat; i++ ) { builder.append(seed); } int remainder = length % seed.length(); builder.append(seed.substring(0, remainder)); String result = builder.toString(); Assert.assertEquals( length, result.length()); return result; } }