| /* |
| * 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. |
| */ |
| package org.netbeans.modules.editor.lib2.view; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.JEditorPane; |
| import javax.swing.text.AttributeSet; |
| import javax.swing.text.BadLocationException; |
| import javax.swing.text.Document; |
| import junit.framework.TestCase; |
| import org.netbeans.junit.Filter; |
| import org.netbeans.junit.NbTestCase; |
| import org.netbeans.spi.editor.highlighting.support.PositionsBag; |
| |
| import static org.netbeans.modules.editor.lib2.view.ViewUpdatesTesting.HI_VIEW; |
| import static org.netbeans.modules.editor.lib2.view.ViewUpdatesTesting.TAB_VIEW; |
| import static org.netbeans.modules.editor.lib2.view.ViewUpdatesTesting.NL_VIEW; |
| import static org.netbeans.modules.editor.lib2.view.ViewUpdatesTesting.P_VIEW; |
| import static org.netbeans.modules.editor.lib2.view.ViewUpdatesTesting.VIEW_BUILDER_TEST_VALUE_NAMES; |
| import org.netbeans.spi.editor.highlighting.support.OffsetsBag; |
| |
| /** |
| * |
| * @author mmetelka |
| */ |
| public class ViewUpdatesExtraFactoryTest extends NbTestCase { |
| |
| public ViewUpdatesExtraFactoryTest(String testName) { |
| super(testName); |
| |
| List<String> includes = new ArrayList<String>(); |
| // includes.add("testExtraHighlightSpansNewline"); |
| // filterTests(includes); |
| } |
| |
| private void filterTests(List<String> includeTestNames) { |
| List<Filter.IncludeExclude> includeTests = new ArrayList<Filter.IncludeExclude>(); |
| for (String testName : includeTestNames) { |
| includeTests.add(new Filter.IncludeExclude(testName, "")); |
| } |
| Filter filter = new Filter(); |
| filter.setIncludes(includeTests.toArray(new Filter.IncludeExclude[includeTests.size()])); |
| setFilter(filter); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| ViewUpdatesTesting.registerTestFactory(); |
| ViewUpdatesTesting.setTestValuesNames(VIEW_BUILDER_TEST_VALUE_NAMES); |
| |
| } |
| |
| @Override |
| protected int timeOut() { |
| return super.timeOut(); |
| // return 10000000; |
| } |
| |
| @Override |
| protected Level logLevel() { |
| return Level.INFO; // null; |
| // return Level.FINEST; |
| } |
| |
| private static void loggingOn() { |
| // FINEST throws ISE for integrity error in EditorView |
| Logger.getLogger("org.netbeans.modules.editor.lib2.view.EditorView").setLevel(Level.FINEST); |
| ViewHierarchyImpl.CHECK_LOG.setLevel(Level.FINEST); |
| // Logger.getLogger("org.netbeans.modules.editor.lib2.view.ViewBuilder").setLevel(LOG_LEVEL); |
| // Logger.getLogger("org.netbeans.modules.editor.lib2.view.ViewUpdates").setLevel(LOG_LEVEL); |
| // Check gap-storage correctness |
| // Logger.getLogger("org.netbeans.modules.editor.lib2.view.EditorBoxViewChildren").setLevel(Level.FINE); |
| } |
| |
| private static void addHighlight(Document doc, PositionsBag bag, int startOffset, int endOffset, AttributeSet attrs) |
| throws BadLocationException |
| { |
| bag.addHighlight(doc.createPosition(startOffset), doc.createPosition(endOffset), attrs); |
| } |
| |
| public void testExtraHighlightSpansNewline() throws Exception { |
| loggingOn(); |
| ViewUpdatesTesting.setTestValues(ViewUpdatesTesting.NO_OP_TEST_VALUE); |
| JEditorPane pane = ViewUpdatesTesting.createPane(); |
| Document doc = pane.getDocument(); |
| final DocumentView docView = DocumentView.get(pane); |
| final PositionsBag highlights = ViewUpdatesTesting.getSingleHighlightingLayer(pane); |
| int offset; |
| String text; |
| int removeLength; |
| int HIGHLIGHT_COUNT = 30; |
| // Test at least GAP_STORAGE_THRESHOLD |
| assert (HIGHLIGHT_COUNT > ViewGapStorage.GAP_STORAGE_THRESHOLD); |
| StringBuilder sbLine = new StringBuilder(200); |
| String hlText = "ab"; |
| for (int i = HIGHLIGHT_COUNT; i > 0; i--) { |
| sbLine.append(hlText); |
| } |
| sbLine.append('\n'); |
| int lineLen = sbLine.length(); |
| int LINE_COUNT = 2; |
| StringBuilder sb = new StringBuilder(400); |
| for (int i = LINE_COUNT; i > 0; i--) { |
| sb.append(sbLine); |
| } |
| |
| text = sb.toString(); |
| offset = 0; |
| doc.insertString(offset, text, null); |
| |
| // Add highlights |
| final PositionsBag hlts = new PositionsBag(doc); |
| offset = 0; |
| for (int i = LINE_COUNT; i > 0; i--) { |
| for (int j = HIGHLIGHT_COUNT; j > 0; j--) { |
| addHighlight(doc, hlts, offset, offset + 2, ViewUpdatesTesting.FONT_ATTRS[j % 2]); |
| offset += hlText.length(); |
| } |
| assert (text.charAt(offset) == '\n'); |
| offset++; // skip newline |
| } |
| doc.render(new Runnable() { |
| @Override |
| public void run() { |
| highlights.setHighlights(hlts); // since non-empty setTestValues() is active no delayed rebuild occurs |
| } |
| }); |
| docView.op.viewsRebuildOrMarkInvalid(); // Manually mark affected children as invalid |
| docView.ensureAllParagraphsChildrenAndLayoutValid(); |
| |
| ViewUpdatesTesting.checkViews(docView, 0, 6, |
| hlText.length(), HI_VIEW, |
| hlText.length(), HI_VIEW, |
| hlText.length(), HI_VIEW |
| ); |
| |
| // Set a test highlight that spans end of first line. View creation should |
| // continue to next line (EVFactory.continueCreation() should be called). |
| TestHighlightsViewFactory testFactory = ViewUpdatesTesting.getTestFactory(pane); |
| List<TestHighlight> testHlts = ViewUpdatesTesting.getHighlightsCopy(testFactory); |
| TestHighlight testHlt = TestHighlight.create( |
| ViewUtils.createPosition(doc, lineLen - 2), |
| ViewUtils.createPosition(doc, lineLen + 1), |
| ViewUpdatesTesting.FONT_ATTRS[2] |
| ); |
| testHlts.add(testHlt); |
| testFactory.setHighlights(testHlts); |
| // No firing of change - just change whether infrastructure handles situation well. |
| // Now perform insert at point where the extra highlight starts. |
| // Force extra view factory to produce view that spans newline. |
| offset = testHlt.startOffset(); // one char before newline |
| text = "x"; |
| // Expect the test factory will get continueCreation() call: |
| // startOffset: end of produced highlight (that spanned newline); held by position => text length incorporated. |
| // endOffset: end of second line + inserted text length |
| testFactory.setContinueCreationRange(testHlt.endOffset() + text.length(), lineLen * 2 + text.length()); |
| |
| ViewUpdatesTesting.setTestValues( |
| /*rebuildCause*/ ViewBuilder.RebuildCause.MOD_UPDATE, |
| /*createLocalViews*/ true, |
| /*startCreationOffset*/ offset - 1, |
| /*matchOffset*/ offset + 1 +text.length(), |
| /*endCreationOffset*/ lineLen + text.length(), // includes '\n' |
| /*bmReuseOffset*/ offset - 1, |
| /*bmReusePView*/ docView.getParagraphView(0), |
| /*bmReuseLocalIndex*/ 29, |
| /*amReuseOffset*/ offset + 2, |
| /*amReusePIndex*/ 0, |
| /*amReusePView*/ docView.getParagraphView(0), |
| /*amReuseLocalIndex*/ 30 |
| ); |
| doc.insertString(offset, text, null); |
| |
| if (docView.getParagraphView(0).children.gapStorage == null) { |
| // TestCase.fail("Expecting non-null gapStorage"); |
| } |
| if (!testFactory.isContinueCreationUnset()) { |
| // TestCase.fail("Expecting continueCreation() called."); |
| } |
| |
| ViewUpdatesTesting.setTestValues(); |
| } |
| |
| public void testNullChildren() throws Exception { |
| loggingOn(); |
| ViewUpdatesTesting.setTestValues(ViewUpdatesTesting.NO_OP_TEST_VALUE); |
| JEditorPane pane = ViewUpdatesTesting.createPane(); |
| Document doc = pane.getDocument(); |
| final DocumentView docView = DocumentView.get(pane); |
| // Insert twice the length of chars that would be otherwise serviced with local views creation |
| int insertCount = ViewBuilder.MAX_CHARS_FOR_CREATE_LOCAL_VIEWS; |
| String insertText = "a\n"; |
| for (int i = 0; i <= insertCount; i++) { |
| doc.insertString(0, insertText, null); |
| } |
| int docLen = doc.getLength(); |
| int lineCount = doc.getDefaultRootElement().getElementCount(); |
| |
| docView.op.releaseChildren(false); |
| docView.ensureLayoutValidForInitedChildren(); |
| docView.children.ensureParagraphsChildrenAndLayoutValid(docView, 0, lineCount / 2, 0, 0); |
| |
| int hlStartOffset = docLen * 1 / 5; |
| int hlStartPIndex = doc.getDefaultRootElement().getElementIndex(hlStartOffset); |
| int hlEndOffset = hlStartOffset * 2; |
| int hlEndPIndex = hlStartPIndex * 2; |
| TestHighlightsViewFactory testFactory = ViewUpdatesTesting.getTestFactory(pane); |
| List<TestHighlight> testHlts = ViewUpdatesTesting.getHighlightsCopy(testFactory); |
| TestHighlight testHlt = TestHighlight.create( |
| ViewUtils.createPosition(doc, hlStartOffset), |
| ViewUtils.createPosition(doc, hlEndOffset), |
| ViewUpdatesTesting.FONT_ATTRS[2] |
| ); |
| testHlts.add(testHlt); |
| testFactory.setHighlights(testHlts); |
| testFactory.fireChange(hlStartOffset, hlEndOffset); |
| docView.op.viewsRebuildOrMarkInvalid(); // Manually mark affected children as invalid |
| |
| docView.children.ensureParagraphsChildrenAndLayoutValid(docView, |
| hlStartPIndex, hlEndPIndex, 0, 0); |
| |
| ViewUpdatesTesting.setTestValues(); |
| } |
| |
| public void testHighlightBeyondDocEnd() throws Exception { |
| loggingOn(); |
| ViewUpdatesTesting.setTestValues(ViewUpdatesTesting.NO_OP_TEST_VALUE); |
| JEditorPane pane = ViewUpdatesTesting.createPane(); |
| Document doc = pane.getDocument(); |
| final DocumentView docView = DocumentView.get(pane); |
| final OffsetsBag highlights = ViewUpdatesTesting.getSingleHighlightingLayerOffsets(pane); |
| String text = "abcd\nefgh"; |
| doc.insertString(0, text, null); |
| highlights.addHighlight(0, 5, ViewUpdatesTesting.FONT_ATTRS[0]); |
| highlights.addHighlight(7, doc.getLength() + 2, ViewUpdatesTesting.FONT_ATTRS[1]); // Beyond doc's end |
| |
| docView.op.viewsRebuildOrMarkInvalid(); // Manually mark affected children as invalid |
| docView.ensureAllParagraphsChildrenAndLayoutValid(); |
| |
| } |
| |
| public void testCustomHighlightBeyondDocEnd() throws Exception { |
| loggingOn(); |
| ViewUpdatesTesting.setTestValues(ViewUpdatesTesting.NO_OP_TEST_VALUE); |
| JEditorPane pane = ViewUpdatesTesting.createPane(); |
| Document doc = pane.getDocument(); |
| final DocumentView docView = DocumentView.get(pane); |
| final TestOffsetsHighlightsContainer highlights = new TestOffsetsHighlightsContainer(); |
| ViewUpdatesTesting.getSingleHighlightingLayerCustom(pane, highlights); |
| highlights.setOffsetPairs(new int[] { 0, 5 }); |
| String text = "abcd\nefgh"; |
| doc.insertString(0, text, null); |
| |
| docView.op.viewsRebuildOrMarkInvalid(); // Manually mark affected children as invalid |
| docView.ensureAllParagraphsChildrenAndLayoutValid(); |
| highlights.setOffsetPairs(new int[] { 3, 9 }); |
| doc.remove(0, doc.getLength()); |
| } |
| |
| } |