/* * Copyright 2003-2016 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 jetbrains.mps.ide.projectPane.favorites; import com.intellij.icons.AllIcons.Toolwindows; import com.intellij.ide.SelectInTarget; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.EmptyIcon; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.ide.projectPane.BaseLogicalViewProjectPane; import jetbrains.mps.ide.projectPane.ProjectPane; import jetbrains.mps.ide.projectPane.ProjectPaneActionGroups; import jetbrains.mps.ide.projectPane.favorites.MPSFavoritesManager.MPSFavoritesListener; import jetbrains.mps.ide.projectPane.favorites.root.FavoritesRoot; import jetbrains.mps.ide.ui.tree.MPSTree; import jetbrains.mps.ide.ui.tree.MPSTreeNode; import jetbrains.mps.ide.ui.tree.TextTreeNode; import jetbrains.mps.ide.ui.tree.smodel.NodeTargetProvider; import jetbrains.mps.openapi.navigation.EditorNavigator; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SNodeReference; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JScrollPane; import java.util.Collections; import java.util.Comparator; import java.util.List; @State( name = "Favorites", storages = @Storage(StoragePathMacros.WORKSPACE_FILE) ) public class FavoritesProjectPane extends BaseLogicalViewProjectPane { public static final String ID = "Favorites"; private MPSFavoritesManager myFavoritesManager; private MPSFavoritesListener myFavoritesListener; private JScrollPane myScrollPane; protected FavoritesProjectPane(Project project, MPSFavoritesManager manager, ProjectView projectView) { super(project, projectView); myFavoritesManager = manager; } @Override public void rebuild() { getTree().rebuildLater(); } @Override public void selectNextModel(SModel md) { // todo: (after remove) } @Override public String getTitle() { return "Favorites"; } @Override public Icon getIcon() { return Toolwindows.ToolWindowFavorites; } @Override @NotNull public String getId() { return ID; } @Override public JComponent createComponent() { if (isComponentCreated()) { rebuild(); return myScrollPane; } myTree = new MyLogicalViewTree(ProjectHelper.toMPSProject(getProject())); myFavoritesListener = new MPSFavoritesListener() { @Override public void rootsChanged(String listName) { refreshMySubIdsAndSelect(listName); getTree().rebuildLater(); } @Override public void listAdded(String listName) { refreshMySubIdsAndSelect(listName); } @Override public void listRemoved(String listName) { String selectedSubId = getSubId(); refreshMySubIdsAndSelect(selectedSubId); } private void refreshMySubIdsAndSelect(String listName) { myFavoritesManager.removeListener(myFavoritesListener); getProjectView().removeProjectPane(FavoritesProjectPane.this); getProjectView().addProjectPane(FavoritesProjectPane.this); myFavoritesManager.addListener(myFavoritesListener); if (ArrayUtil.find(myFavoritesManager.getFavoriteNames(), listName) == -1) { getProjectView().changeView(ProjectPane.ID); return; } getProjectView().changeView(ID, listName); } }; myFavoritesManager.addListener(myFavoritesListener); rebuild(); myScrollPane = ScrollPaneFactory.createScrollPane(myTree); return myScrollPane; } @Override protected boolean isComponentCreated() { return myScrollPane != null; } @Override public MPSTree getTree() { return (MPSTree) myTree; } @Override public ActionCallback updateFromRoot(boolean restoreExpandedPaths) { getTree().rebuildLater(); return new ActionCallback(); } @Override public void select(Object element, VirtualFile file, boolean requestFocus) { } @Override public int getWeight() { return 10; } @Override public SelectInTarget createSelectInTarget() { return new FavoritesSelectInTarget(myProject); } @NotNull @Override public String[] getSubIds() { return myFavoritesManager.getFavoriteNames(); } @NotNull @Override public String getPresentableSubIdName(@NotNull String subId) { return subId; } @Override public String toString() { return "Favorites"; } private class MyLogicalViewTree extends MPSTree { private final jetbrains.mps.project.Project myProject; MyLogicalViewTree(jetbrains.mps.project.Project mpsProject) { myProject = mpsProject; } @Override protected MPSTreeNode rebuild() { String subId = getSubId(); TextTreeNode invisibleRoot = new TextTreeNode(subId == null ? "Favorites" : subId); invisibleRoot.setIcon(EmptyIcon.create(10)); List<Object> objectList = myFavoritesManager.getRoots(subId); if (objectList == null || objectList.size() == 0) { invisibleRoot.setText("There is nothing to display."); return invisibleRoot; } for (Object o : objectList.toArray()) { FavoritesRoot favoritesRoot = FavoritesRoot.createForValue(myProject, o); if (favoritesRoot == null) continue; MPSTreeNode newChild = favoritesRoot.createTreeNode(); if (newChild == null) { myFavoritesManager.removeRoots(subId, Collections.singletonList(o)); continue; } invisibleRoot.add(newChild); } return invisibleRoot; } @Override protected void doubleClick(@NotNull MPSTreeNode nodeToClick) { if (nodeToClick instanceof NodeTargetProvider) { final SNodeReference navigationTarget = ((NodeTargetProvider) nodeToClick).getNavigationTarget(); if (navigationTarget != null) { new EditorNavigator(myProject).shallFocus(true).selectIfChild().open(navigationTarget); return; } // fall-through } super.doubleClick(nodeToClick); } @Override protected void autoscroll(@NotNull MPSTreeNode nodeToClick) { // FIXME this is copy of ProjectPaneTree#autoscroll, refactor to minimize duplication of code if (nodeToClick instanceof NodeTargetProvider) { final SNodeReference navigationTarget = ((NodeTargetProvider) nodeToClick).getNavigationTarget(); if (navigationTarget != null) { new EditorNavigator(myProject).shallFocus(false).selectIfChild().open(navigationTarget); return; } // fall-through } super.autoscroll(nodeToClick); } @Override public Comparator<Object> getChildrenComparator() { return getTreeChildrenComparator(); } @Override public boolean isAutoOpen() { return getProjectView().isAutoscrollToSource(getId()); } @Override protected String getPopupMenuPlace() { return ActionPlaces.FAVORITES_VIEW_POPUP; } @Override protected ActionGroup createPopupActionGroup(final MPSTreeNode node) { return ProjectPaneActionGroups.getActionGroup(node); } } }