blob: 5c6786eaaa763d2b0857c08eb0c8815f982671fe [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.intellij.uiDesigner.projectView;
import com.intellij.ide.DeleteProvider;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.TreeStructureProvider;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.BasePsiNode;
import com.intellij.ide.util.DeleteHandler;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.uiDesigner.binding.FormClassIndex;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class FormMergerTreeStructureProvider implements TreeStructureProvider {
private final Project myProject;
public FormMergerTreeStructureProvider(Project project) {
myProject = project;
}
public Collection<AbstractTreeNode> modify(AbstractTreeNode parent, Collection<AbstractTreeNode> children, ViewSettings settings) {
if (parent.getValue() instanceof Form) return children;
// Optimization. Check if there are any forms at all.
boolean formsFound = false;
for (AbstractTreeNode node : children) {
if (node.getValue() instanceof PsiFile) {
PsiFile file = (PsiFile)node.getValue();
if (file.getFileType() == StdFileTypes.GUI_DESIGNER_FORM) {
formsFound = true;
break;
}
}
}
if (!formsFound) return children;
Collection<AbstractTreeNode> result = new LinkedHashSet<AbstractTreeNode>(children);
ProjectViewNode[] copy = children.toArray(new ProjectViewNode[children.size()]);
for (ProjectViewNode element : copy) {
PsiClass psiClass = null;
if (element.getValue() instanceof PsiClass) {
psiClass = (PsiClass)element.getValue();
}
else if (element.getValue() instanceof PsiClassOwner) {
final PsiClass[] psiClasses = ((PsiClassOwner) element.getValue()).getClasses();
if (psiClasses.length == 1) {
psiClass = psiClasses[0];
}
}
if (psiClass == null) continue;
String qName = psiClass.getQualifiedName();
if (qName == null) continue;
List<PsiFile> forms;
try {
forms = FormClassIndex.findFormsBoundToClass(myProject, qName);
}
catch (ProcessCanceledException e) {
continue;
}
Collection<BasePsiNode<? extends PsiElement>> formNodes = findFormsIn(children, forms);
if (!formNodes.isEmpty()) {
Collection<PsiFile> formFiles = convertToFiles(formNodes);
Collection<BasePsiNode<? extends PsiElement>> subNodes = new ArrayList<BasePsiNode<? extends PsiElement>>();
//noinspection unchecked
subNodes.add((BasePsiNode<? extends PsiElement>) element);
subNodes.addAll(formNodes);
result.add(new FormNode(myProject, new Form(psiClass, formFiles), settings, subNodes));
result.remove(element);
result.removeAll(formNodes);
}
}
return result;
}
public Object getData(Collection<AbstractTreeNode> selected, String dataId) {
if (selected != null) {
if (Form.DATA_KEY.is(dataId)) {
List<Form> result = new ArrayList<Form>();
for(AbstractTreeNode node: selected) {
if (node.getValue() instanceof Form) {
result.add((Form) node.getValue());
}
}
if (!result.isEmpty()) {
return result.toArray(new Form[result.size()]);
}
}
else if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) {
for(AbstractTreeNode node: selected) {
if (node.getValue() instanceof Form) {
return new MyDeleteProvider(selected);
}
}
}
}
return null;
}
private static Collection<PsiFile> convertToFiles(Collection<BasePsiNode<? extends PsiElement>> formNodes) {
ArrayList<PsiFile> psiFiles = new ArrayList<PsiFile>();
for (AbstractTreeNode treeNode : formNodes) {
psiFiles.add((PsiFile)treeNode.getValue());
}
return psiFiles;
}
private static Collection<BasePsiNode<? extends PsiElement>> findFormsIn(Collection<AbstractTreeNode> children, List<PsiFile> forms) {
if (children.isEmpty() || forms.isEmpty()) return Collections.emptyList();
ArrayList<BasePsiNode<? extends PsiElement>> result = new ArrayList<BasePsiNode<? extends PsiElement>>();
HashSet<PsiFile> psiFiles = new HashSet<PsiFile>(forms);
for (final AbstractTreeNode child : children) {
if (child instanceof BasePsiNode) {
//noinspection unchecked
BasePsiNode<? extends PsiElement> treeNode = (BasePsiNode<? extends PsiElement>)child;
//noinspection SuspiciousMethodCalls
if (psiFiles.contains(treeNode.getValue())) result.add(treeNode);
}
}
return result;
}
private static class MyDeleteProvider implements DeleteProvider {
private final PsiElement[] myElements;
public MyDeleteProvider(final Collection<AbstractTreeNode> selected) {
myElements = collectFormPsiElements(selected);
}
public void deleteElement(@NotNull DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
DeleteHandler.deletePsiElement(myElements, project);
}
public boolean canDeleteElement(@NotNull DataContext dataContext) {
return DeleteHandler.shouldEnableDeleteAction(myElements);
}
private static PsiElement[] collectFormPsiElements(Collection<AbstractTreeNode> selected) {
Set<PsiElement> result = new HashSet<PsiElement>();
for(AbstractTreeNode node: selected) {
if (node.getValue() instanceof Form) {
Form form = (Form)node.getValue();
result.add(form.getClassToBind());
ContainerUtil.addAll(result, form.getFormFiles());
}
else if (node.getValue() instanceof PsiElement) {
result.add((PsiElement) node.getValue());
}
}
return PsiUtilCore.toPsiElementArray(result);
}
}
}