Java tutorial
/******************************************************************************* * Copyright (c) 2011 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Google, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.wb.tests.designer.editor; import org.eclipse.wb.core.editor.IDesignPageSite; import org.eclipse.wb.core.model.JavaInfo; import org.eclipse.wb.core.model.ObjectInfo; import org.eclipse.wb.gef.core.EditPart; import org.eclipse.wb.gef.core.tools.CreationTool; import org.eclipse.wb.internal.core.DesignerPlugin; import org.eclipse.wb.internal.core.editor.DesignPageSite; import org.eclipse.wb.internal.core.editor.UndoManager; import org.eclipse.wb.internal.core.editor.structure.components.IComponentsTree; import org.eclipse.wb.internal.core.preferences.IPreferenceConstants; import org.eclipse.wb.internal.core.utils.ast.BodyDeclarationTarget; import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils; import org.eclipse.wb.internal.swing.model.component.ComponentInfo; import org.eclipse.wb.internal.swing.model.component.ContainerInfo; import org.eclipse.wb.tests.designer.core.RefactoringTestUtils; import org.eclipse.wb.tests.designer.core.annotations.DisposeProjectAfter; import org.eclipse.wb.tests.designer.swing.SwingGefTest; import org.eclipse.wb.tests.gef.UIRunnable; import org.eclipse.wb.tests.gef.UiContext; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.actions.JdtActionConstants; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.part.FileEditorInput; import org.apache.commons.lang.ArrayUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; /** * Test for {@link UndoManager}. * * @author scheglov_ke */ public class UndoManagerTest extends SwingGefTest { //////////////////////////////////////////////////////////////////////////// // // Life cycle // //////////////////////////////////////////////////////////////////////////// @Override protected void tearDown() throws Exception { super.tearDown(); { IPreferenceStore preferences = DesignerPlugin.getPreferences(); preferences.setToDefault(IPreferenceConstants.P_EDITOR_LAYOUT); } } //////////////////////////////////////////////////////////////////////////// // // Exit zone :-) XXX // //////////////////////////////////////////////////////////////////////////// public void _test_exit() throws Exception { System.exit(0); } //////////////////////////////////////////////////////////////////////////// // // Selection/expanded restoring after reparse // //////////////////////////////////////////////////////////////////////////// /** * Test that selection is restored after undo/redo. */ public void test_undoRedo() throws Exception { openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); String initialSource = m_lastEditor.getSource(); IActionBars actionBars = m_designerEditor.getEditorSite().getActionBars(); // do edit String source_withButton; { ContainerInfo frame = (ContainerInfo) m_contentJavaInfo; ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); assertTrue(m_viewerCanvas.getSelectedEditParts().isEmpty()); // select content pane canvas.moveTo(contentPane, 10, 10); canvas.click(); assertSelectionModels(contentPane); // create JButton JavaInfo newButton; { newButton = loadCreationTool("javax.swing.JButton"); assertTrue(m_viewerCanvas.getEditDomain().getActiveTool() instanceof CreationTool); // use creation tool canvas.moveTo(contentPane, 100, 50); canvas.click(); assertEditor("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " {", " JButton button = new JButton('New button');", " getContentPane().add(button, BorderLayout.NORTH);", " }", " }", "}"); source_withButton = m_lastEditor.getSource(); } // check selection on new JButton assertSelectionModels(newButton); assertExpandedComponents(frame, contentPane); } // undo { actionBars.getGlobalActionHandler("undo").run(); waitEventLoop(0); fetchContentFields(); // check source assertEquals(initialSource, m_lastEditor.getSource()); // check selection ContainerInfo frame = (ContainerInfo) m_contentJavaInfo; ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); assertSelectionModels(contentPane); } // redo { actionBars.getGlobalActionHandler("redo").run(); waitEventLoop(0); fetchContentFields(); // check source assertEquals(source_withButton, m_lastEditor.getSource()); ContainerInfo frame = (ContainerInfo) m_contentJavaInfo; ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); // check selection/expansion assertSelectionModels(contentPane.getChildrenComponents().get(0)); assertExpandedComponents(frame, contentPane); } } /** * Test for case when we modify only logic of application, but not its GUI, so can keep old * selection. */ public void test_modifyLogicAndSwitchDesign() throws Exception { openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); // prepare ICompilationUnit ICompilationUnit compilationUnit; { Field field = ReflectionUtils.getFieldByName(m_designPage.getClass(), "m_compilationUnit"); compilationUnit = (ICompilationUnit) field.get(m_designPage); } // { ContainerInfo frame = (ContainerInfo) m_contentJavaInfo; ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); // assertTrue(m_viewerCanvas.getSelectedEditParts().isEmpty()); // select content pane canvas.click(150, 100, 1); assertSelectionModels(contentPane); // switch to Source openSourcePage(); // modify ICompilationUnit compilationUnit.getBuffer().replace(0, 0, "// abc\n"); waitEventLoop(0); // switch to Design openDesignPage(); // "contentPane" should be selected, despite reparsing { List<EditPart> selectedEditParts = m_viewerCanvas.getSelectedEditParts(); assertEquals(1, selectedEditParts.size()); EditPart selectedEditPart = selectedEditParts.get(0); assertEquals(contentPane.toString(), selectedEditPart.getModel().toString()); } } } /** * When document is changed, but not WBP editor is active (for example Java editor is also * opened), then we should not parse. But when WBP editor is activated later, then we should * parse. */ public void test_modifyInParallelJavaEditor() throws Exception { IWorkbenchPage activePage = DesignerPlugin.getActivePage(); ContainerInfo originalContainer = openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); // open in Java editor ISourceViewer sourceViewer; { IFile file = getFileSrc("test/Test.java"); IEditorPart javaEditor = activePage.openEditor(new FileEditorInput(file), JavaUI.ID_CU_EDITOR, true, IWorkbenchPage.MATCH_NONE); sourceViewer = (ISourceViewer) ReflectionUtils.invokeMethod(javaEditor, "getViewer()"); } // update document, WBP editor is not active, so no changes yet sourceViewer.getDocument().replace(0, 0, "// comment\n"); fetchContentFields(); assertSame(originalContainer, m_contentJavaInfo); // active WBP editor, document was changed, so reparse activePage.activate(m_designerEditor); waitEventLoop(0); fetchContentFields(); assertNotSame(originalContainer, m_contentJavaInfo); } //////////////////////////////////////////////////////////////////////////// // // Expansion // //////////////////////////////////////////////////////////////////////////// /** * Test that when we select component, its parent become expanded. */ public void test_expandOnSelection() throws Exception { ContainerInfo frame = openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); IComponentsTree componentTree = DesignPageSite.Helper.getSite(frame).getComponentTree(); // collapse all { componentTree.setExpandedElements(ArrayUtils.EMPTY_OBJECT_ARRAY); assertEquals(0, componentTree.getExpandedElements().length); } // select "contentPane", "frame" should be expanded { canvas.select(contentPane); assertExpandedComponents(frame); } } /** * Sometimes expansion paths are remembered for wrong dump, so this causes later exception. */ public void test_expandRemembered_bug_0() throws Exception { ContainerInfo frame = openContainer("public class Test extends JFrame {", " public Test() {", " JPanel panel = new JPanel();", " getContentPane().add(panel);", " panel.add(new JButton());", " }", "}"); IActionBars actionBars = m_designerEditor.getEditorSite().getActionBars(); ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); ContainerInfo panel = (ContainerInfo) contentPane.getChildrenComponents().get(0); ComponentInfo button = panel.getChildrenComponents().get(0); // select "button", "frame" and "contentPane" are expanded canvas.select(button); assertExpandedComponents(frame, contentPane, panel); // delete "panel" with "button" canvas.select(panel); actionBars.getGlobalActionHandler(ActionFactory.DELETE.getId()).run(); assertEquals( getSource("package test;", "import java.awt.*;", "import java.awt.event.*;", "import javax.swing.*;", "import javax.swing.border.*;", "public class Test extends JFrame {", " public Test() {", " }", "}"), m_lastEditor.getModelUnit().getSource()); // switch to "Source" openSourcePage(); // organize imports actionBars.getGlobalActionHandler(JdtActionConstants.ORGANIZE_IMPORTS).run(); assertEquals(getSourceDQ("package test;", "import javax.swing.JFrame;", "public class Test extends JFrame {", " public Test() {", " }", "}"), m_lastEditor.getModelUnit().getSource()); // switch to "Design", no exception expected openDesignPage(); } //////////////////////////////////////////////////////////////////////////// // // Expand on open // //////////////////////////////////////////////////////////////////////////// /** * When we open editor, it automatically expands components from root, until there is one element.<br> * Here we have {@link JFrame} with empty "contentPane", so {@link JFrame} should be expanded. */ public void test_expandOnOpen_1() throws Exception { ContainerInfo frame = openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); // "frame" should be expanded assertExpandedComponents(frame); } /** * When we open editor, it automatically expands components from root, until there is one element.<br> * Here we have {@link JFrame} with "contentPane" as its single child, so {@link JFrame} and * "contentPane" should be expanded. */ public void test_expandOnOpen_2() throws Exception { ContainerInfo frame = openContainer("public class Test extends JFrame {", " public Test() {", " getContentPane().add(new JButton());", " getContentPane().add(new JButton());", " }", "}"); ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); // "frame" and "contentPane" should be expanded assertExpandedComponents(frame, contentPane); } /** * When we open editor, it automatically expands components from root, until there is one element.<br> * Here we have {@link JFrame} with "contentPane" as its single child, so {@link JFrame} and * "contentPane" should be expanded. But {@link JPanel} on "content" pane is not only child of * "contentPane", so should be not expanded. */ public void test_expandOnOpen_3() throws Exception { ContainerInfo frame = openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " {", " JPanel panel = new JPanel();", " getContentPane().add(panel);", " panel.add(new JButton());", " }", " getContentPane().add(new JButton());", " }", "}"); ContainerInfo contentPane = (ContainerInfo) frame.getChildrenComponents().get(0); // "frame" and "contentPane" should be expanded assertExpandedComponents(frame, contentPane); } /** * Assert that {@link IComponentsTree} has expanded expanded objects. */ private void assertExpandedComponents(ObjectInfo... expandedObjects) { IComponentsTree componentTree = DesignPageSite.Helper.getSite(m_contentJavaInfo).getComponentTree(); assertTrue(Arrays.equals(expandedObjects, componentTree.getExpandedElements())); } //////////////////////////////////////////////////////////////////////////// // // Restore selection // //////////////////////////////////////////////////////////////////////////// /** * Test that we restore selection after reparse. */ public void test_restoreSelection_good() throws Exception { openContainer("public class Test extends JPanel {", " public Test() {", " {", " JButton button_1 = new JButton();", " add(button_1);", " }", " {", " JButton button_2 = new JButton();", " add(button_2);", " }", " }", "}"); // select tree.select(getJavaInfoByName("button_2")); tree.assertPrimarySelected(getJavaInfoByName("button_2")); // reparse { IDesignPageSite.Helper.getSite(m_contentJavaInfo).reparse(); fetchContentFields(); } // check selection tree.assertPrimarySelected(getJavaInfoByName("button_2")); } /** * Test that if we can not restore selection, we just ignore this, without exceptions. */ public void test_restoreSelection_whenComponentDisappears() throws Exception { setFileContentSrc("test/MyPanel.java", getTestSource("public class MyPanel extends JPanel {", " private JButton m_button = new JButton();", " public MyPanel() {", " add(m_button);", " }", " public JButton getButton() {", " return m_button;", " }", "}")); waitForAutoBuild(); // parse openContainer("public class Test extends JPanel {", " public Test() {", " add(new MyPanel());", " }", "}"); // select { ComponentInfo button = getJavaInfoByName("getButton()"); tree.select(button); tree.assertPrimarySelected(button); } // use "MyPanel" which does not expose "getButton()" setFileContentSrc("test/MyPanel.java", getTestSource("public class MyPanel extends JPanel {", " private JButton m_button = new JButton();", " public MyPanel() {", " add(m_button);", " }", "}")); waitForAutoBuild(); // reparse { IDesignPageSite.Helper.getSite(m_contentJavaInfo).reparse(); fetchContentFields(); } // can not restore selection of "getButton()", because it is not visible in "MyPanel" anymore tree.assertSelectedEmpty(); } //////////////////////////////////////////////////////////////////////////// // // Read-Only // //////////////////////////////////////////////////////////////////////////// /** * Test edit read-only file. */ public void test_readOnly_Yes() throws Exception { String[] expectedSource = new String[] { "// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", " void foo() {", " }", "}" }; test_readOnly(IDialogConstants.YES_LABEL, false, expectedSource, expectedSource); } /** * Test edit read-only file. */ public void test_readOnly_No() throws Exception { test_readOnly(IDialogConstants.NO_LABEL, true, new String[] { "// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", " void foo() {", " }", "}" }, new String[] { "// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}" }); } private void test_readOnly(final String buttonId, boolean expectedAccess, String[] expectedSource1, String[] expectedSource2) throws Exception { openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); ICompilationUnit unit = m_lastEditor.getModelUnit(); // modify file access to read-only mode IFile unitFile = (IFile) unit.getUnderlyingResource(); ResourceAttributes attributes = new ResourceAttributes(); attributes.setReadOnly(true); unitFile.setResourceAttributes(attributes); // change AST TypeDeclaration typeDeclaration = (TypeDeclaration) m_lastEditor.getAstUnit().types().get(0); m_lastEditor.addMethodDeclaration("void foo()", new ArrayList<String>(), new BodyDeclarationTarget(typeDeclaration, false)); // do commit changes new UiContext().executeAndCheck(new UIRunnable() { public void run(UiContext context) throws Exception { m_lastEditor.commitChanges(); } }, new UIRunnable() { public void run(UiContext context) throws Exception { context.useShell("Read-only File Encountered"); context.clickButton(buttonId); } }); // waitEventLoop(0); waitForAutoBuild(); // check result assertEquals(expectedAccess, unitFile.isReadOnly()); assertEquals(getTestSource(expectedSource1), m_lastEditor.getSource()); assertEquals(getTestSource(expectedSource2), unit.getBuffer().getContents()); } //////////////////////////////////////////////////////////////////////////// // // Cases // //////////////////////////////////////////////////////////////////////////// @DisposeProjectAfter public void test_showDesign_switchToSource_rename_showDesign() throws Exception { openContainer("// filler filler filler", "public class Test extends JFrame {", " public Test() {", " }", "}"); ICompilationUnit unit = m_lastEditor.getModelUnit(); // switch to "Source" openSourcePage(); // rename compilation unit RefactoringTestUtils.renameType(unit.getType("Test"), "Test_2"); waitEventLoop(0); // again switch to "Design" openDesignPage(); } /** * Test that renaming {@link ICompilationUnit} while "Design" page is active does not cause * exceptions. */ @DisposeProjectAfter public void test_showDesign_rename() throws Exception { openContainer("public class Test extends JFrame {", " public static void main2(String[] args) {", " Test frame = new Test();", " frame.setVisible(true);", " }", " public Test() {", " }", "}"); // rename { ICompilationUnit unit = m_lastEditor.getModelUnit(); RefactoringTestUtils.renameType(unit.getType("Test"), "Test_2"); } // OK? for (int i = 0; i < 10; i++) { waitEventLoop(0); } assertNoLoggedExceptions(); } }