Package javax.swing.text

Source Code of javax.swing.text.FlowView_FlowStrategyTest$PartFactory

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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.
*/
/**
* @author Alexey A. Ivanov
*/
package javax.swing.text;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BasicSwingTestCase;
import javax.swing.event.DocumentEvent.EventType;
import javax.swing.text.AbstractDocument.BranchElement;
import javax.swing.text.AbstractDocument.DefaultDocumentEvent;
import javax.swing.text.AbstractDocument.ElementEdit;
import javax.swing.text.FlowView.FlowStrategy;
import javax.swing.text.FlowViewTest.FlowViewImplWithFactory;
import javax.swing.text.GlyphView.GlyphPainter;
import javax.swing.text.GlyphViewTest.EmptyPainter;
import junit.framework.TestCase;

public class FlowView_FlowStrategyTest extends TestCase {
    private DefaultStyledDocument doc;

    private Element root;

    private Element p1;

    private Element p1L;

    private DefaultDocumentEvent event;

    private FlowView view;

    private View row;

    private FlowStrategy strategy;

    static final List<Object> viewsCreated = new ArrayList<Object>();

    private static final Rectangle alloc = new Rectangle(3, 7, 37, 141);

    private static final int X_AXIS = View.X_AXIS;

    private static final int Y_AXIS = View.Y_AXIS;

    private static boolean excellentBreak;

    protected static class TestStrategy extends FlowStrategy {
        @Override
        protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) {
            View result = super.createView(fv, startOffset, spanLeft, rowIndex);
            viewsCreated.add(result);
            return result;
        }

        @Override
        public String toString() {
            return "logStrategy";
        }
    }

    protected static class FixedPainter extends EmptyPainter {
        protected static final GlyphPainter PAINTER = new FixedPainter();

        private FixedPainter() {
        }

        @Override
        public int getBoundedPosition(GlyphView v, int startOffset, float x, float len) {
            int result = (int) len / PartView.CHAR_WIDTH + startOffset;
            return result <= v.getEndOffset() ? result : v.getEndOffset();
        }

        @Override
        public float getSpan(GlyphView v, int startOffset, int endOffset, TabExpander e, float x) {
            return PartView.CHAR_WIDTH * (endOffset - startOffset);
        }
    }

    protected static class PartView extends GlyphView {
        private static int count = 0;

        private int id = count++;

        static final int CHAR_WIDTH = 4;

        static final int CHAR_HEIGHT = 9;

        public PartView(Element element) {
            super(element);
            setGlyphPainter(FixedPainter.PAINTER);
        }

        @Override
        public float getPreferredSpan(int axis) {
            int result = axis == X_AXIS ? (int) super.getPreferredSpan(axis) : CHAR_HEIGHT;
            return result;
        }

        @Override
        public String toString() {
            final Element e = getElement();
            return "glyph(" + id + ", " + e.getName() + "[" + e.getStartOffset() + ", "
                    + e.getEndOffset() + "]" + ")  [" + getStartOffset() + ", "
                    + getEndOffset() + "]";
        }
    }

    protected static class PartFactory implements ViewFactory {
        public View create(Element element) {
            return new PartView(element);
        }
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        doc = new DefaultStyledDocument();
        doc.insertString(0, "this is the test text with some long words in p2\n"
        //                   |              |
                //  0123456789012345678901234567890123456789012345678
                //  0         1         2         3         4
                + "Long words: internationalization, localization", null);
        root = doc.getDefaultRootElement();
        p1 = root.getElement(0);
        // Break the first paragraph into several
        doc.writeLock();
        Element[] leaves = new Element[] { doc.createLeafElement(p1, null, 0, 17),
                doc.createLeafElement(p1, null, 17, 32),
                doc.createLeafElement(p1, null, 32, 49) };
        ((BranchElement) p1).replace(0, p1.getElementCount(), leaves);
        doc.writeUnlock();
        p1L = p1.getElement(0);
        // Initialize the view
        view = new FlowViewImplWithFactory(p1, Y_AXIS, new PartFactory());
        strategy = view.strategy = new TestStrategy();
        view.loadChildren(null);
        row = view.createRow();
        view.append(row);
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        viewsCreated.clear();
    }

    public void testInsertUpdate() {
        event = doc.new DefaultDocumentEvent(4, 5, EventType.INSERT);
        event.addEdit(new ElementEdit(p1, 0, new Element[] { p1L }, new Element[] { p1L }));
        event.end();
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.insertUpdate(view, event, alloc);
        assertTrue(view.isAllocationValid());
    }

    public void testInsertUpdateNull() {
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.insertUpdate(view, null, null);
        assertFalse(view.isAllocationValid());
        assertFalse(view.isLayoutValid(X_AXIS));
        assertFalse(view.isLayoutValid(Y_AXIS));
    }

    public void testRemoveUpdate() {
        event = doc.new DefaultDocumentEvent(4, 5, EventType.REMOVE);
        event.addEdit(new ElementEdit(p1, 0, new Element[] { p1L }, new Element[] { p1L }));
        event.end();
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.removeUpdate(view, event, alloc);
        assertTrue(view.isAllocationValid());
    }

    public void testRemoveUpdateNull() {
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.removeUpdate(view, null, null);
        assertFalse(view.isAllocationValid());
        assertFalse(view.isLayoutValid(X_AXIS));
        assertFalse(view.isLayoutValid(Y_AXIS));
    }

    public void testChangedUpdate() {
        event = doc.new DefaultDocumentEvent(4, 5, EventType.CHANGE);
        event.addEdit(new ElementEdit(p1, 0, new Element[] { p1L }, new Element[] { p1L }));
        event.end();
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.changedUpdate(view, event, alloc);
        assertTrue(view.isAllocationValid());
    }

    public void testChangedUpdateNull() {
        view.layout(alloc.width, alloc.height);
        assertTrue(view.isAllocationValid());
        view.strategy.changedUpdate(view, null, null);
        assertFalse(view.isAllocationValid());
        assertFalse(view.isLayoutValid(X_AXIS));
        assertFalse(view.isLayoutValid(Y_AXIS));
    }

    /**
     * Tests <code>adjustRow</code> in ordinary "environment".
     */
    public void testAdjustRowOrdinary() {
        view.append(row);
        View[] views = new View[view.layoutPool.getViewCount() - 1];
        for (int i = 0; i < views.length; i++) {
            views[i] = view.layoutPool.getView(i);
        }
        row.replace(0, 0, views);
        view.layoutSpan = (int) (view.layoutPool.getView(0).getPreferredSpan(X_AXIS) + view.layoutPool
                .getView(1).getPreferredSpan(X_AXIS) / 2);
        assertEquals(2, row.getViewCount());
        strategy.adjustRow(view, 0, view.layoutSpan, 0);
        assertEquals(2, row.getViewCount());
        // The first physical view will be the same as the logical one (copied)
        assertSame(view.layoutPool.getView(0), row.getView(0));
        assertSame(row, view.layoutPool.getView(0).getParent());
        assertSame(row, row.getView(0).getParent());
        // The second is broken
        final View second = row.getView(1);
        assertEquals(view.layoutPool.getView(1).getStartOffset(), second.getStartOffset());
        assertEquals(22, row.getView(1).getEndOffset());
        assertSame(view.layoutPool, view.layoutPool.getView(1).getParent());
        assertSame(row, second.getParent());
        assertEquals(0, row.getStartOffset());
        assertEquals(22, row.getEndOffset());
    }

    /**
     * Tests <code>adjustRow</code> in a situation where the first and the third
     * views return <code>GoodBreakWeight</code> but the second returns
     * <code>ExcellentBreakWeight</code>. Here the second view will be broken
     * although it fits (the third doesn't fit the layoutSpan only).
     */
    public void testAdjustRowGoodExcellentGood() {
        View[] views = new View[view.layoutPool.getViewCount()];
        view.layoutSpan = 0;
        for (int i = 0; i < views.length; i++) {
            excellentBreak = i == 1;
            // Special view to get the required break weights easily
            views[i] = new PartView(view.layoutPool.getView(i).getElement()) {
                private final boolean excellent = excellentBreak;

                @Override
                public int getBreakWeight(int axis, float x, float len) {
                    return excellent ? ExcellentBreakWeight : GoodBreakWeight;
                }

                @Override
                public View breakView(int axis, int start, float x, float len) {
                    return createFragment(start, start + (getEndOffset() - getStartOffset())
                            / 2);
                }
            };
            int span = (int) views[i].getPreferredSpan(X_AXIS);
            if (i == views.length - 1) {
                span = span / 2;
            }
            view.layoutSpan += span;
        }
        row.replace(0, 0, views);
        // layoutSpan includes the first and the second views entirely and
        // only the half of the third.
        // The view will break on the second one, that's why the number of
        // children reduces from 3 to 2.
        assertEquals(3, row.getViewCount());
        strategy.adjustRow(view, 0, view.layoutSpan, 0);
        assertEquals(2, row.getViewCount());
        View child = row.getView(0);
        assertEquals(0, child.getStartOffset());
        assertEquals(17, child.getEndOffset());
        child = row.getView(1);
        assertEquals(17, child.getStartOffset());
        assertEquals(24, child.getEndOffset());
        assertEquals(0, row.getStartOffset());
        assertEquals(24, row.getEndOffset());
    }

    /**
     * Adjust the missing row. (Causes expected exception.)
     */
    public void testAdjustRowNoRow() {
        assertEquals(1, view.getViewCount());
        try {
            strategy.adjustRow(view, 1, view.layoutSpan, 0);
            fail("NullPointerException or ArrayIndexOutOfBoundsException " + "is expected");
        } catch (NullPointerException e) {
        } catch (ArrayIndexOutOfBoundsException e) {
        }
    }

    /**
     * Layout the missing row. (Causes expected exception.)
     */
    public void testLayoutRowNoRow() {
        assertEquals(1, view.getViewCount());
        try {
            strategy.layoutRow(view, 1, 0);
            fail("NullPointerException or ArrayIndexOutOfBoundsException " + "is expected");
        } catch (NullPointerException e) {
        } catch (ArrayIndexOutOfBoundsException e) {
        }
    }

    /**
     * Tests the situation where the layoutSpan is exhausted.
     */
    public void testLayoutRowSpanExhausted() {
        view.layoutSpan = (int) (view.layoutPool.getView(0).getPreferredSpan(X_AXIS) + view.layoutPool
                .getView(1).getPreferredSpan(X_AXIS) / 2);
        assertEquals(98, view.layoutSpan);
        int nextOffset = strategy.layoutRow(view, 0, 5);
        assertEquals(2, row.getViewCount());
        assertEquals(1, view.getViewCount());
        assertEquals(2, viewsCreated.size());
        final View child1 = row.getView(0);
        assertSame(viewsCreated.get(0), child1);
        assertEquals(5, child1.getStartOffset());
        assertEquals(view.layoutPool.getView(0).getEndOffset(), child1.getEndOffset());
        assertSame(viewsCreated.get(1), view.layoutPool.getView(1));
        final View child2 = row.getView(1);
        assertNotSame(viewsCreated.get(1), child2);
        assertEquals(child1.getEndOffset(), child2.getStartOffset());
        assertEquals(27, child2.getEndOffset());
        assertTrue(view.layoutSpan > child1.getPreferredSpan(X_AXIS)
                + child2.getPreferredSpan(X_AXIS));
        assertEquals(child2.getEndOffset(), nextOffset);
        assertEquals(row.getEndOffset(), nextOffset);
    }

    /**
     * Tests the situation where <code>createView</code> returns
     * <code>null</code>.
     */
    public void testLayoutRowNullReturned() {
        strategy = view.strategy = new TestStrategy() {
            private int count = 0;

            @Override
            protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) {
                return count++ == 2 ? null : super.createView(fv, startOffset, spanLeft,
                        rowIndex);
            }
        };
        assertEquals(Short.MAX_VALUE, view.layoutSpan);
        int nextOffset = strategy.layoutRow(view, 0, 5);
        assertEquals(2, row.getViewCount());
        assertEquals(1, view.getViewCount());
        assertEquals(2, viewsCreated.size());
        final View child1 = row.getView(0);
        assertSame(viewsCreated.get(0), child1);
        assertEquals(5, child1.getStartOffset());
        assertEquals(view.layoutPool.getView(0).getEndOffset(), child1.getEndOffset());
        assertSame(viewsCreated.get(1), view.layoutPool.getView(1));
        final View child2 = row.getView(1);
        assertSame(viewsCreated.get(1), child2);
        assertEquals(child1.getEndOffset(), child2.getStartOffset());
        assertEquals(view.layoutPool.getView(1).getEndOffset(), child2.getEndOffset());
        assertTrue(view.layoutSpan > child1.getPreferredSpan(X_AXIS)
                + child2.getPreferredSpan(X_AXIS));
        assertEquals(child2.getEndOffset(), nextOffset);
        assertEquals(row.getEndOffset(), nextOffset);
    }

    /**
     * Tests the situation where a view requests a forced break.
     */
    public void testLayoutRowForcedBreak() {
        strategy = view.strategy = new TestStrategy() {
            private int count = 0;

            @Override
            protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) {
                if (count++ == 1) {
                    Element e = fv.layoutPool.getView(count - 1).getElement();
                    return new PartView(e) {
                        private final int half = (getEndOffset() - getStartOffset()) / 2;
                        {
                            viewsCreated.add(this);
                        }

                        @Override
                        public int getBreakWeight(int axis, float x, float len) {
                            if (len > CHAR_WIDTH * half) {
                                return ForcedBreakWeight;
                            }
                            return super.getBreakWeight(axis, x, len);
                        }

                        @Override
                        public View breakView(int axis, int startOffset, float x, float len) {
                            if (len > CHAR_WIDTH * half) {
                                return createFragment(startOffset, startOffset + half);
                            }
                            return super.breakView(axis, startOffset, x, len);
                        }
                    };
                }
                return super.createView(fv, startOffset, spanLeft, rowIndex);
            }
        };
        assertEquals(Short.MAX_VALUE, view.layoutSpan);
        int nextOffset = strategy.layoutRow(view, 0, 5);
        assertEquals(2, row.getViewCount());
        assertEquals(1, view.getViewCount());
        assertEquals(2, viewsCreated.size());
        final View child1 = row.getView(0);
        assertSame(viewsCreated.get(0), child1);
        assertEquals(5, child1.getStartOffset());
        assertEquals(view.layoutPool.getView(0).getEndOffset(), child1.getEndOffset());
        assertNotSame(viewsCreated.get(1), view.layoutPool.getView(1));
        final View forced = (View) viewsCreated.get(1);
        assertEquals(view.layoutPool.getView(1).getStartOffset(), forced.getStartOffset());
        assertEquals(view.layoutPool.getView(1).getEndOffset(), forced.getEndOffset());
        assertNotSame(viewsCreated.get(1), row.getView(1));
        final View child2 = row.getView(1);
        assertEquals(child1.getEndOffset(), child2.getStartOffset());
        assertEquals((view.layoutPool.getView(1).getEndOffset() + view.layoutPool.getView(1)
                .getStartOffset()) / 2, child2.getEndOffset());
        assertTrue(view.layoutSpan > child1.getPreferredSpan(X_AXIS)
                + child2.getPreferredSpan(X_AXIS));
        assertEquals(child2.getEndOffset(), nextOffset);
        assertEquals(row.getEndOffset(), nextOffset);
    }

    /**
     * Tests how FlowView lays out the second paragraph (with very long words).
     */
    public void testLayout() {
        view = new FlowViewImplWithFactory(root.getElement(1), Y_AXIS, new PartFactory());
        strategy = view.strategy = new TestStrategy();
        view.loadChildren(null);
        view.layoutSpan = PartView.CHAR_WIDTH * 13;
        strategy.layout(view);
        String[] text = new String[] { "Long words: ", "international", "ization, ",
                "localization\n" };
        assertEquals(text.length, view.getViewCount());
        for (int i = 0; i < view.getViewCount(); i++) {
            final View row = view.getView(i);
            assertEquals("i = " + i + " " + row, 1, row.getViewCount());
            assertEquals(text[i], getText(row.getView(0)));
        }
    }

    /**
     * Tests that "old" children contained are removed from
     * the <code>FlowView</code> before layout is performed.
     */
    public void testLayoutRemoved() {
        View[] dummy = new View[] { new PlainView(p1L), new PlainView(p1) };
        view.replace(0, view.getViewCount(), dummy);
        assertEquals(2, view.getViewCount());
        view.layoutSpan = Integer.MAX_VALUE;
        view.strategy.layout(view);
        assertEquals(1, view.getViewCount());
    }

    public void testGetLogicalView() {
        assertSame(view.layoutPool, view.strategy.getLogicalView(view));
    }

    public void testCreateView() {
        assertSame(view.layoutPool.getView(0), strategy.createView(view, 0, view.layoutSpan, 0));
        assertSame(view.layoutPool.getView(0), strategy
                .createView(view, 0, view.layoutSpan, -1));
        assertSame(view.layoutPool.getView(0), strategy.createView(view, 0, -1, 0));
        View created = strategy.createView(view, 3, view.layoutSpan, 0);
        View logical = view.layoutPool.getView(0);
        assertNotSame(logical, created);
        assertEquals(3, created.getStartOffset());
        assertEquals(logical.getEndOffset(), created.getEndOffset());
        created = strategy.createView(view, 3, 2, 0);
        assertEquals(3, created.getStartOffset());
        assertEquals(logical.getEndOffset(), created.getEndOffset());
        created = strategy.createView(view, logical.getEndOffset(), 2, 0);
        logical = view.layoutPool.getView(1);
        assertSame(logical, created);
        created = strategy.createView(view, logical.getStartOffset() + 2, 2, 0);
        assertNotSame(logical, created);
        assertEquals(logical.getStartOffset() + 2, created.getStartOffset());
        assertEquals(logical.getEndOffset(), created.getEndOffset());
        logical = view.layoutPool.getView(view.layoutPool.getViewCount() - 1);
        created = strategy.createView(view, logical.getEndOffset() - 1, 2, 0);
        assertEquals(logical.getEndOffset() - 1, created.getStartOffset());
        assertEquals(logical.getEndOffset(), created.getEndOffset());
        try {
            assertNull(strategy.createView(view, logical.getEndOffset(), 2, 0));
        } catch (ArrayIndexOutOfBoundsException e) {
            if (BasicSwingTestCase.isHarmony()) {
                fail("ArrayIndexOutOfBoundsException is unexpected");
            }
        }
    }

    private static String getText(View v) {
        return ((GlyphView) v).getText(v.getStartOffset(), v.getEndOffset()).toString();
    }
}
TOP

Related Classes of javax.swing.text.FlowView_FlowStrategyTest$PartFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
y>