/* * Copyright 2003-2015 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.devkit.cellExplorer.cellsTree; import jetbrains.mps.icons.MPSIcons.CellExplorer; import jetbrains.mps.ide.devkit.cellExplorer.CellExplorerTool; import jetbrains.mps.ide.devkit.cellExplorer.MPSTreeWithAction; import jetbrains.mps.ide.ui.tree.MPSTreeNode; import jetbrains.mps.ide.ui.tree.TextTreeNode; import jetbrains.mps.nodeEditor.EditorComponent; import jetbrains.mps.openapi.editor.cells.CellTraversalUtil; import jetbrains.mps.openapi.editor.cells.EditorCell; import jetbrains.mps.openapi.editor.update.UpdaterListener; import jetbrains.mps.openapi.editor.update.UpdaterListenerAdapter; import jetbrains.mps.smodel.ModelReadRunnable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import java.util.Collections; import java.util.List; public class CellsTree extends MPSTreeWithAction { private final UpdaterListener mySynchronizationListener = new MyUpdaterListenerAdapter(); private EditorComponent myCurrentEditor; public CellsTree() { setRootVisible(true); } @Override protected void doInit(MPSTreeNode node, Runnable nodeInitRunnable) { // myCurrentEditor could not be null, otherwise we won't get to CellNode.init() super.doInit(node, new ModelReadRunnable(myCurrentEditor.getEditorContext().getRepository().getModelAccess(), nodeInitRunnable)); } @Override protected MPSTreeNode rebuild() { if (myCurrentEditor == null || myCurrentEditor.getRootCell() == null) { TextTreeNode rv = new TextTreeNode("No editor selected"); rv.setIcon(CellExplorer.CellExplorer); return rv; } else { return new CellNode(myCurrentEditor.getRootCell()); } } public void setCurrentEditor(EditorComponent cellEditor) { if (myCurrentEditor == cellEditor) return; if (myCurrentEditor != null) { myCurrentEditor.getUpdater().removeListener(mySynchronizationListener); } myCurrentEditor = cellEditor; if (myCurrentEditor != null) { myCurrentEditor.getUpdater().addListener(mySynchronizationListener); } rebuildNow(); } @Override public void dispose() { setCurrentEditor(null); super.dispose(); } public void showCellInTree(EditorCell cell) { EditorComponent cellEditor = (EditorComponent) cell.getEditorComponent(); setCurrentEditor(cellEditor); MPSTreeNode current = findCellNode(cell); if (current == null) { CellExplorerTool.LOG.warn("Can't find cell in tree"); return; } selectNode(current); } private MPSTreeNode findCellNode(EditorCell cell) { if (cell == null) return null; List<EditorCell> path = getEditorCellPath(cell); MPSTreeNode current = getRootNode(); if (current.getUserObject() != path.get(0)) return null; for (int i = 1; i < path.size(); i++) { if (!current.isInitialized()) current.init(); current = current.findExactChildWith(path.get(i)); if (current == null) return null; } return current; } @NotNull private static List<EditorCell> getEditorCellPath(EditorCell cell) { List<EditorCell> path = CellTraversalUtil.getParents(cell, true); Collections.reverse(path); return path; } @Nullable public EditorCell getCellByPath(@Nullable TreePath path) { if (path == null) return null; Object[] nodes = path.getPath(); for (int i = nodes.length - 1; i >= 0; i--) { Object node = nodes[i]; if (!(node instanceof DefaultMutableTreeNode)) continue; Object userObject = ((DefaultMutableTreeNode) node).getUserObject(); if (userObject instanceof EditorCell) return ((EditorCell) userObject); } return null; } private class MyUpdaterListenerAdapter extends UpdaterListenerAdapter { private CellNode myCachedPropertyCellNode = null; @Override public void cellSynchronizedWithModel(EditorCell cell) { if (cell == null) { return; } CellNode cellNode; if (myCachedPropertyCellNode != null && cell == myCachedPropertyCellNode.getUserObject()) { cellNode = myCachedPropertyCellNode; } else { cellNode = (CellNode) findCellNode(cell); myCachedPropertyCellNode = cellNode; } if (cellNode == null) { return; } cellNode.updatePresentation(true, false); repaint(); } @Override public void editorUpdated(jetbrains.mps.openapi.editor.EditorComponent editorComponent) { rebuildLater(); } } }