diff options
author | Jens Ole Lauridsen <jlauridsen@google.com> | 2015-07-08 10:00:17 -0700 |
---|---|---|
committer | Deepanshu Gupta <deepanshu@google.com> | 2015-07-13 17:39:16 -0700 |
commit | 2a26b3683dd1180a4343415945714eaa012350e4 (patch) | |
tree | 28676f075c29d2e506932a72c4e0777cd8ee926d /designer | |
parent | 31f5ff1614f1ed9afe3fd43619940d81a82c59c5 (diff) | |
download | idea-2a26b3683dd1180a4343415945714eaa012350e4.tar.gz |
Nele: Create component tree (pure restructure).
As a preparation for adding drag and drop to the structure pane,
create a class for controlling the tree separate from the structure
pane that also controls the properties panel.
Change-Id: I8696eefce9a56bc087ae6140ba609601f03f3371
(cherry picked from commit 6879840782a434d166924d9f48b04da257ccc1a1)
Diffstat (limited to 'designer')
-rw-r--r-- | designer/src/com/android/tools/idea/uibuilder/structure/NlComponentTree.java | 336 | ||||
-rw-r--r-- | designer/src/com/android/tools/idea/uibuilder/structure/NlStructurePanel.java | 314 | ||||
-rw-r--r-- | designer/testSrc/com/android/tools/idea/uibuilder/structure/NlComponentTreeTest.java (renamed from designer/testSrc/com/android/tools/idea/uibuilder/structure/NlStructurePanelTest.java) | 27 |
3 files changed, 355 insertions, 322 deletions
diff --git a/designer/src/com/android/tools/idea/uibuilder/structure/NlComponentTree.java b/designer/src/com/android/tools/idea/uibuilder/structure/NlComponentTree.java new file mode 100644 index 00000000000..b28d470dff8 --- /dev/null +++ b/designer/src/com/android/tools/idea/uibuilder/structure/NlComponentTree.java @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2015 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.tools.idea.uibuilder.structure; + +import com.android.SdkConstants; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.tools.idea.uibuilder.model.*; +import com.android.tools.idea.uibuilder.surface.DesignSurface; +import com.android.tools.idea.uibuilder.surface.DesignSurfaceListener; +import com.android.tools.idea.uibuilder.surface.ScreenView; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.IJSwingUtilities; +import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.util.ui.update.MergingUpdateQueue; +import com.intellij.util.ui.update.Update; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.Insets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import static com.android.SdkConstants.*; +import static com.android.tools.idea.uibuilder.property.NlPropertiesPanel.UPDATE_DELAY_MSECS; +import static com.intellij.util.Alarm.ThreadToUse.SWING_THREAD; + +public class NlComponentTree extends Tree implements Disposable, DesignSurfaceListener, ModelListener, SelectionListener { + private static final Insets INSETS = new Insets(0, 6, 0, 6); + + private final StructureTreeDecorator myDecorator; + private final Map<XmlTag, DefaultMutableTreeNode> myTag2Node; + private final AtomicBoolean mySelectionIsUpdating; + private final MergingUpdateQueue myUpdateQueue; + + private NlModel myModel; + private boolean myWasExpanded; + + public NlComponentTree() { + myDecorator = StructureTreeDecorator.get(); + myTag2Node = new HashMap<XmlTag, DefaultMutableTreeNode>(); + mySelectionIsUpdating = new AtomicBoolean(false); + myUpdateQueue = new MergingUpdateQueue("android.layout.structure-pane", UPDATE_DELAY_MSECS, true, null, this, null, SWING_THREAD); + DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(null); + DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); + setModel(treeModel); + getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + setBorder(new EmptyBorder(INSETS)); + setRootVisible(false); + setShowsRootHandles(false); + setToggleClickCount(1); + ToolTipManager.sharedInstance().registerComponent(this); + TreeUtil.installActions(this); + createCellRenderer(); + addTreeSelectionListener(new StructurePaneSelectionListener()); +//todo: new StructureSpeedSearch(myTree); +//todo: enableDnD(myTree); + } + + public void setDesignSurface(@Nullable DesignSurface designSurface) { + setModel(designSurface != null && designSurface.getCurrentScreenView() != null ? designSurface.getCurrentScreenView().getModel() : null); + } + + private void setModel(@Nullable NlModel model) { + if (myModel != null) { + myModel.removeListener(this); + myModel.getSelectionModel().removeListener(this); + } + myModel = model; + if (myModel != null) { + myModel.addListener(this); + myModel.getSelectionModel().addListener(this); + } + loadData(); + } + + @Override + public void dispose() { + if (myModel != null) { + myModel.removeListener(this); + myModel.getSelectionModel().removeListener(this); + } + } + + private void createCellRenderer() { + setCellRenderer(new ColoredTreeCellRenderer() { + @Override + public void customizeCellRenderer(@NonNull JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; + NlComponent component = (NlComponent)node.getUserObject(); + if (component == null) { + return; + } + myDecorator.decorate(component, this, true); + } + }); + } + + private void loadData() { + updateHierarchy(true); + } + + private void invalidateUI() { + IJSwingUtilities.updateComponentTreeUI(this); + } + + private void updateHierarchy(final boolean firstLoad) { + ApplicationManager.getApplication().assertIsDispatchThread(); + setPaintBusy(true); + myUpdateQueue.queue(new Update("updateComponentStructure") { + @Override + public void run() { + try { + mySelectionIsUpdating.set(true); + if (firstLoad) { + myWasExpanded = false; + myTag2Node.clear(); + } + DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)getModel().getRoot(); + List<NlComponent> components = myModel != null ? myModel.getComponents() : null; + replaceChildNodes(rootNode, components); + expandOnce(); + invalidateUI(); + } finally { + setPaintBusy(false); + mySelectionIsUpdating.set(false); + } + if (firstLoad) { + updateSelection(); + } + } + }); + } + + private void replaceChildNodes(@NonNull DefaultMutableTreeNode node, @Nullable List<NlComponent> subComponents) { + node.removeAllChildren(); + if (subComponents != null) { + for (NlComponent child : subComponents) { + node.add(makeNode(child)); + } + } + } + + @NonNull + private DefaultMutableTreeNode makeNode(@NonNull NlComponent component) { + DefaultMutableTreeNode node = myTag2Node.get(component.getTag()); + if (node == null) { + node = new DefaultMutableTreeNode(component); + myTag2Node.put(component.getTag(), node); + } else { + node.setUserObject(component); + } + replaceChildNodes(node, component.children); + return node; + } + + private void expandOnce() { + if (myWasExpanded) { + return; + } + final DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)getModel().getRoot(); + if (rootNode.isLeaf()) { + return; + } + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + DefaultMutableTreeNode nodeToExpand = rootNode; + NlComponent component = findComponentToExpandTo(); + if (component != null) { + nodeToExpand = myTag2Node.get(component.getTag()); + if (nodeToExpand == null) { + nodeToExpand = rootNode; + } + } + TreePath path = new TreePath(nodeToExpand.getPath()); + expandPath(path); + while (path != null) { + path = path.getParentPath(); + expandPath(path); + } + myWasExpanded = true; + } + }); + } + + // Find a component that it would be interesting to expand to when a new file is viewed. + // If the file has an App Bar lookup something that may be user content. + @Nullable + private NlComponent findComponentToExpandTo() { + if (myModel == null || myModel.getComponents().isEmpty()) { + return null; + } + NlComponent root = myModel.getComponents().get(0); + NlComponent childOfInterest = root; + if (root.getTagName().equals(COORDINATOR_LAYOUT)) { + // Find first child that is not an AppBarLayout and not anchored to anything. + for (NlComponent child : root.getChildren()) { + if (!child.getTagName().equals(APP_BAR_LAYOUT) && + child.getTag().getAttribute(ATTR_LAYOUT_ANCHOR, AUTO_URI) == null) { + // If this is a NestedScrollView look inside: + if (child.getTagName().equals(SdkConstants.CLASS_NESTED_SCROLL_VIEW) && child.children != null && !child.children.isEmpty()) { + child = child.getChild(0); + } + childOfInterest = child; + break; + } + } + } + + if (childOfInterest == null || childOfInterest.children == null || childOfInterest.children.isEmpty()) { + return childOfInterest; + } + return childOfInterest.children.get(childOfInterest.children.size() - 1); + } + + private void updateSelection() { + if (!mySelectionIsUpdating.compareAndSet(false, true)) { + return; + } + try { + clearSelection(); + if (myModel != null) { + for (NlComponent component : myModel.getSelectionModel().getSelection()) { + DefaultMutableTreeNode node = myTag2Node.get(component.getTag()); + if (node != null) { + TreePath path = new TreePath(node.getPath()); + expandPath(path); + addSelectionPath(path); + } + } + } + } finally { + mySelectionIsUpdating.set(false); + } + } + + // ---- Implemented SelectionListener ---- + @Override + public void selectionChanged(@NonNull SelectionModel model, @NonNull List<NlComponent> selection) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + updateSelection(); + } + }); + } + + // ---- Implemented ModelListener ---- + @Override + public void modelChanged(@NonNull NlModel model) { + } + + @Override + public void modelRendered(@NonNull NlModel model) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + updateHierarchy(false); + } + }); + } + + // ---- Implemented DesignSurfaceListener ---- + + @Override + public void componentSelectionChanged(@NonNull DesignSurface surface, @NonNull List<NlComponent> newSelection) { + } + + @Override + public void screenChanged(@NonNull DesignSurface surface, @Nullable ScreenView screenView) { + setModel(screenView != null ? screenView.getModel() : null); + } + + @Override + public void modelChanged(@NonNull DesignSurface surface, @Nullable NlModel model) { + if (model != null) { + modelRendered(model); + } + } + + private class StructurePaneSelectionListener implements TreeSelectionListener { + @Override + public void valueChanged(TreeSelectionEvent treeSelectionEvent) { + if (!mySelectionIsUpdating.compareAndSet(false, true)) { + return; + } + try { + List<NlComponent> selected = new ArrayList<NlComponent>(); + TreePath[] paths = getSelectionPaths(); + if (paths != null) { + for (TreePath path : paths) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + selected.add((NlComponent)node.getUserObject()); + } + } + myModel.getSelectionModel().setSelection(selected); + } finally { + mySelectionIsUpdating.set(false); + } + } + } +} diff --git a/designer/src/com/android/tools/idea/uibuilder/structure/NlStructurePanel.java b/designer/src/com/android/tools/idea/uibuilder/structure/NlStructurePanel.java index fc91009ec97..23b31c81490 100644 --- a/designer/src/com/android/tools/idea/uibuilder/structure/NlStructurePanel.java +++ b/designer/src/com/android/tools/idea/uibuilder/structure/NlStructurePanel.java @@ -15,97 +15,40 @@ */ package com.android.tools.idea.uibuilder.structure; -import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; -import com.android.tools.idea.uibuilder.model.*; import com.android.tools.idea.uibuilder.property.NlPropertiesPanel; import com.android.tools.idea.uibuilder.surface.DesignSurface; -import com.android.tools.idea.uibuilder.surface.DesignSurfaceListener; -import com.android.tools.idea.uibuilder.surface.ScreenView; import com.intellij.designer.LightToolWindowContent; -import com.intellij.ide.dnd.aware.DnDAwareTree; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.ui.Splitter; -import com.intellij.psi.xml.XmlTag; -import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.ScrollPaneFactory; -import com.intellij.util.IJSwingUtilities; -import com.intellij.util.ui.UIUtil; -import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.util.ui.update.MergingUpdateQueue; -import com.intellij.util.ui.update.Update; import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; import java.awt.*; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import static com.android.SdkConstants.*; -import static com.android.tools.idea.uibuilder.property.NlPropertiesPanel.UPDATE_DELAY_MSECS; -import static com.intellij.util.Alarm.ThreadToUse.SWING_THREAD; import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER; import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; -public class NlStructurePanel extends JPanel implements LightToolWindowContent, DesignSurfaceListener, ModelListener, SelectionListener { - private static final Insets INSETS = new Insets(0, 6, 0, 6); - - private final DnDAwareTree myTree; - private final StructureTreeDecorator myDecorator; - private final Map<XmlTag, DefaultMutableTreeNode> myTag2Node; - private final AtomicBoolean mySelectionIsUpdating; +public class NlStructurePanel extends JPanel implements LightToolWindowContent { + private final NlComponentTree myTree; private final NlPropertiesPanel myPropertiesPanel; - private final MergingUpdateQueue myUpdateQueue; - - private NlModel myModel; - private boolean myWasExpanded; public NlStructurePanel(@NonNull DesignSurface designSurface) { - myDecorator = StructureTreeDecorator.get(); - myTree = new DnDAwareTree(); - myTag2Node = new HashMap<XmlTag, DefaultMutableTreeNode>(); - mySelectionIsUpdating = new AtomicBoolean(false); + myTree = new NlComponentTree(); JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER); myPropertiesPanel = new NlPropertiesPanel(designSurface); - myUpdateQueue = new MergingUpdateQueue( - "android.layout.structure-pane", UPDATE_DELAY_MSECS, true, null, designSurface, null, SWING_THREAD); Splitter splitter = new Splitter(true, 0.4f); splitter.setFirstComponent(pane); splitter.setSecondComponent(myPropertiesPanel); - initTree(); setLayout(new BorderLayout()); add(splitter, BorderLayout.CENTER); setDesignSurface(designSurface); } public void setDesignSurface(@Nullable DesignSurface designSurface) { + myTree.setDesignSurface(designSurface); myPropertiesPanel.setDesignSurface(designSurface); - setModel(designSurface != null && designSurface.getCurrentScreenView() != null ? designSurface.getCurrentScreenView().getModel() : null); - } - - private void setModel(@Nullable NlModel model) { - if (myModel != null) { - myModel.removeListener(this); - myModel.getSelectionModel().removeListener(this); - } - myModel = model; - if (myModel != null) { - myModel.addListener(this); - myModel.getSelectionModel().addListener(this); - } - loadData(); } public JComponent getPanel() { @@ -114,256 +57,11 @@ public class NlStructurePanel extends JPanel implements LightToolWindowContent, @Override public void dispose() { - if (myModel != null) { - myModel.removeListener(this); - myModel.getSelectionModel().removeListener(this); - } + myTree.dispose(); } @VisibleForTesting - JTree getTree() { + JTree getTree2() { return myTree; } - - private void initTree() { - DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(null); - DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); - myTree.setModel(treeModel); - myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - myTree.setBorder(new EmptyBorder(INSETS)); - myTree.setRootVisible(false); - myTree.setShowsRootHandles(false); - myTree.setToggleClickCount(1); - ToolTipManager.sharedInstance().registerComponent(myTree); - TreeUtil.installActions(myTree); - createCellRenderer(myTree); - myTree.addTreeSelectionListener(new StructurePaneSelectionListener()); -//todo: new StructureSpeedSearch(myTree); -//todo: enableDnD(myTree); - } - - private void createCellRenderer(@NonNull JTree tree) { - tree.setCellRenderer(new ColoredTreeCellRenderer() { - @Override - public void customizeCellRenderer(@NonNull JTree tree, - Object value, - boolean selected, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; - NlComponent component = (NlComponent)node.getUserObject(); - if (component == null) { - return; - } - myDecorator.decorate(component, this, true); - } - }); - } - - private void loadData() { - updateHierarchy(true); - } - - private void invalidateUI() { - IJSwingUtilities.updateComponentTreeUI(myTree); - } - - private void updateHierarchy(final boolean firstLoad) { - ApplicationManager.getApplication().assertIsDispatchThread(); - myTree.setPaintBusy(true); - myUpdateQueue.queue(new Update("updateComponentStructure") { - @Override - public void run() { - try { - mySelectionIsUpdating.set(true); - if (firstLoad) { - myWasExpanded = false; - myTag2Node.clear(); - } - DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)myTree.getModel().getRoot(); - List<NlComponent> components = myModel != null ? myModel.getComponents() : null; - replaceChildNodes(rootNode, components); - expandOnce(); - invalidateUI(); - } finally { - myTree.setPaintBusy(false); - mySelectionIsUpdating.set(false); - } - if (firstLoad) { - updateSelection(); - } - } - }); - } - - private void replaceChildNodes(@NonNull DefaultMutableTreeNode node, @Nullable List<NlComponent> subComponents) { - node.removeAllChildren(); - if (subComponents != null) { - for (NlComponent child : subComponents) { - node.add(makeNode(child)); - } - } - } - - @NonNull - private DefaultMutableTreeNode makeNode(@NonNull NlComponent component) { - DefaultMutableTreeNode node = myTag2Node.get(component.getTag()); - if (node == null) { - node = new DefaultMutableTreeNode(component); - myTag2Node.put(component.getTag(), node); - } else { - node.setUserObject(component); - } - replaceChildNodes(node, component.children); - return node; - } - - private void expandOnce() { - if (myWasExpanded) { - return; - } - final DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)myTree.getModel().getRoot(); - if (rootNode.isLeaf()) { - return; - } - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - DefaultMutableTreeNode nodeToExpand = rootNode; - NlComponent component = findComponentToExpandTo(); - if (component != null) { - nodeToExpand = myTag2Node.get(component.getTag()); - if (nodeToExpand == null) { - nodeToExpand = rootNode; - } - } - TreePath path = new TreePath(nodeToExpand.getPath()); - myTree.expandPath(path); - while (path != null) { - path = path.getParentPath(); - myTree.expandPath(path); - } - myWasExpanded = true; - } - }); - } - - // Find a component that it would be interesting to expand to when a new file is viewed. - // If the file has an App Bar lookup something that may be user content. - @Nullable - private NlComponent findComponentToExpandTo() { - if (myModel == null || myModel.getComponents().isEmpty()) { - return null; - } - NlComponent root = myModel.getComponents().get(0); - NlComponent childOfInterest = root; - if (root.getTagName().equals(COORDINATOR_LAYOUT)) { - // Find first child that is not an AppBarLayout and not anchored to anything. - for (NlComponent child : root.getChildren()) { - if (!child.getTagName().equals(APP_BAR_LAYOUT) && - child.getTag().getAttribute(ATTR_LAYOUT_ANCHOR, AUTO_URI) == null) { - // If this is a NestedScrollView look inside: - if (child.getTagName().equals(SdkConstants.CLASS_NESTED_SCROLL_VIEW) && child.children != null && !child.children.isEmpty()) { - child = child.getChild(0); - } - childOfInterest = child; - break; - } - } - } - - if (childOfInterest == null || childOfInterest.children == null || childOfInterest.children.isEmpty()) { - return childOfInterest; - } - return childOfInterest.children.get(childOfInterest.children.size() - 1); - } - - private void updateSelection() { - if (!mySelectionIsUpdating.compareAndSet(false, true)) { - return; - } - try { - myTree.clearSelection(); - if (myModel != null) { - for (NlComponent component : myModel.getSelectionModel().getSelection()) { - DefaultMutableTreeNode node = myTag2Node.get(component.getTag()); - if (node != null) { - TreePath path = new TreePath(node.getPath()); - myTree.expandPath(path); - myTree.addSelectionPath(path); - } - } - } - } finally { - mySelectionIsUpdating.set(false); - } - } - - // ---- Implemented SelectionListener ---- - @Override - public void selectionChanged(@NonNull SelectionModel model, @NonNull List<NlComponent> selection) { - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { - updateSelection(); - } - }); - } - - // ---- Implemented ModelListener ---- - @Override - public void modelChanged(@NonNull NlModel model) { - } - - @Override - public void modelRendered(@NonNull NlModel model) { - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { - updateHierarchy(false); - } - }); - } - - // ---- Implemented DesignSurfaceListener ---- - - @Override - public void componentSelectionChanged(@NonNull DesignSurface surface, @NonNull List<NlComponent> newSelection) { - } - - @Override - public void screenChanged(@NonNull DesignSurface surface, @Nullable ScreenView screenView) { - setModel(screenView != null ? screenView.getModel() : null); - } - - @Override - public void modelChanged(@NonNull DesignSurface surface, @Nullable NlModel model) { - if (model != null) { - modelRendered(model); - } - } - - private class StructurePaneSelectionListener implements TreeSelectionListener { - @Override - public void valueChanged(TreeSelectionEvent treeSelectionEvent) { - if (!mySelectionIsUpdating.compareAndSet(false, true)) { - return; - } - try { - List<NlComponent> selected = new ArrayList<NlComponent>(); - TreePath[] paths = myTree.getSelectionPaths(); - if (paths != null) { - for (TreePath path : myTree.getSelectionPaths()) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); - selected.add((NlComponent)node.getUserObject()); - } - } - myModel.getSelectionModel().setSelection(selected); - } finally { - mySelectionIsUpdating.set(false); - } - } - } } diff --git a/designer/testSrc/com/android/tools/idea/uibuilder/structure/NlStructurePanelTest.java b/designer/testSrc/com/android/tools/idea/uibuilder/structure/NlComponentTreeTest.java index b9ef57d6a63..db9a8ca92bf 100644 --- a/designer/testSrc/com/android/tools/idea/uibuilder/structure/NlStructurePanelTest.java +++ b/designer/testSrc/com/android/tools/idea/uibuilder/structure/NlComponentTreeTest.java @@ -25,7 +25,6 @@ import com.android.tools.idea.uibuilder.surface.ScreenView; import org.jetbrains.annotations.NotNull; import org.mockito.Mock; -import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import java.util.Iterator; @@ -34,13 +33,13 @@ import static com.android.SdkConstants.*; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -public class NlStructurePanelTest extends LayoutTestCase { +public class NlComponentTreeTest extends LayoutTestCase { @Mock private DesignSurface mySurface; @Mock private ScreenView myScreen; private NlModel myModel; - private NlStructurePanel myPanel; + private NlComponentTree myTree; @Override public void setUp() throws Exception { @@ -50,13 +49,13 @@ public class NlStructurePanelTest extends LayoutTestCase { when(myScreen.getModel()).thenReturn(myModel); when(myScreen.getSelectionModel()).thenReturn(myModel.getSelectionModel()); when(mySurface.getCurrentScreenView()).thenReturn(myScreen); - myPanel = new NlStructurePanel(mySurface); + myTree = new NlComponentTree(); + myTree.setDesignSurface(mySurface); } public void testTreeStructure() { - JTree tree = myPanel.getTree(); NlComponent expectedRoot = myModel.getComponents().get(0); - DefaultMutableTreeNode hidden = (DefaultMutableTreeNode)tree.getModel().getRoot(); + DefaultMutableTreeNode hidden = (DefaultMutableTreeNode)myTree.getModel().getRoot(); assertEquals(1, hidden.getChildCount()); DefaultMutableTreeNode root = (DefaultMutableTreeNode)hidden.getFirstChild(); assertEquals("Unexpected root", expectedRoot, root.getUserObject()); @@ -68,16 +67,15 @@ public class NlStructurePanelTest extends LayoutTestCase { } public void testSelectionInTreeIsPropagatedToModel() { - JTree tree = myPanel.getTree(); - assertNull(tree.getSelectionPaths()); + assertNull(myTree.getSelectionPaths()); assertFalse(myModel.getSelectionModel().getSelection().iterator().hasNext()); - DefaultMutableTreeNode hidden = (DefaultMutableTreeNode)tree.getModel().getRoot(); + DefaultMutableTreeNode hidden = (DefaultMutableTreeNode)myTree.getModel().getRoot(); DefaultMutableTreeNode root = (DefaultMutableTreeNode)hidden.getFirstChild(); DefaultMutableTreeNode node1 = (DefaultMutableTreeNode)root.getChildAt(1); DefaultMutableTreeNode node2 = (DefaultMutableTreeNode)root.getChildAt(2); - tree.addSelectionPath(new TreePath(node1.getPath())); - tree.addSelectionPath(new TreePath(node2.getPath())); + myTree.addSelectionPath(new TreePath(node1.getPath())); + myTree.addSelectionPath(new TreePath(node2.getPath())); Iterator<NlComponent> selected = myModel.getSelectionModel().getSelection().iterator(); assertEquals(node1.getUserObject(), selected.next()); @@ -86,17 +84,18 @@ public class NlStructurePanelTest extends LayoutTestCase { } public void testSelectionInModelIsShownInTree() { - JTree tree = myPanel.getTree(); - assertNull(tree.getSelectionPaths()); + assertNull(myTree.getSelectionPaths()); assertFalse(myModel.getSelectionModel().getSelection().iterator().hasNext()); NlComponent layout = myModel.getComponents().get(0); NlComponent text = layout.getChild(0); NlComponent button = layout.getChild(1); + assert text != null; + assert button != null; myModel.getSelectionModel().toggle(text); myModel.getSelectionModel().toggle(button); - TreePath[] selection = tree.getSelectionPaths(); + TreePath[] selection = myTree.getSelectionPaths(); assertEquals(2, selection.length); assertEquals(text, ((DefaultMutableTreeNode)selection[0].getLastPathComponent()).getUserObject()); assertEquals(button, ((DefaultMutableTreeNode)selection[1].getLastPathComponent()).getUserObject()); |