/** Replaces a node with another, preserving attributes */ public static SNode replaceWithAnother(@NotNull SNode node, SNode replacer) { SNode nodeParent = node.getParent(); if (nodeParent == null) { SModel model = node.getModel(); if (model != null) { node.delete(); model.addRootNode(replacer); } return replacer; } SContainmentLink role = node.getContainmentLink(); assert role != null; if (replacer != null) { // old and new child can have the same node Id // thus it is important to remove old child first SNode anchor = node.getNextSibling(); nodeParent.removeChild(node); SNode replacerParent = replacer.getParent(); if (replacerParent != null) { replacerParent.removeChild(replacer); } nodeParent.insertChildBefore(role, replacer, anchor); } else { nodeParent.removeChild(node); } return replacer; }
private static List<INodeSubstituteAction> createPrimaryChildSubstituteActions( SNode parentNode, SNode currentChild, SNode childConcept, IChildNodeSetter childSetter, IOperationContext context) { if (childConcept == null) { return Collections.emptyList(); } final IScope scope = context.getScope(); String childConceptFqName = NameUtil.nodeFQName(childConcept); Set<String> concepts = new HashSet<String>(); for (Language l : SModelOperations.getLanguages(parentNode.getModel(), scope)) { concepts.addAll( LanguageHierarchyCache.getInstance() .getDefaultSubstitutableDescendantsOf(childConceptFqName, l)); } List<INodeSubstituteAction> actions = new ArrayList<INodeSubstituteAction>(); for (String fqName : concepts) { SNode applicableConcept = SModelUtil.findConceptDeclaration(fqName, scope); assert applicableConcept != null : "No concept " + fqName; actions.addAll( createDefaultActions(applicableConcept, parentNode, currentChild, childSetter, context)); } return actions; }
public boolean canExecute(EditorContext context) { EditorCell selectedCell = getCellToPasteTo((EditorCell) context.getSelectedCell()); if (selectedCell == null) { return false; } SNode selectedNode = selectedCell.getSNode(); if (selectedNode == null || jetbrains.mps.util.SNodeOperations.isDisposed(selectedNode)) { return false; } List<SNode> pasteNodes = CopyPasteUtil.getNodesFromClipboard(selectedNode.getModel()); if (pasteNodes == null || pasteNodes.isEmpty()) { return CopyPasteUtil.isConversionAvailable(selectedNode.getModel(), selectedNode); } if (!new NodePaster(pasteNodes).canPaste(selectedCell)) { LOG.debug("Couldn't paste node here"); return false; } return true; }
/** * Returns whether the given node belongs to the repository (or to one of its parent * repositories). */ public static boolean isAccessible(@NotNull SNode node, @NotNull SRepository inRepository) { SModel model = node.getModel(); if (model == null) return false; SRepository mrep = model.getRepository(); if (mrep == null) return false; mrep.getModelAccess().checkReadAccess(); if (inRepository == mrep) { return true; } // FIXME this is a hack to deal with incomplete story of repository relationship. // We have at least two repositories, ProjectRepository and MPSModuleRepository, and with // repository.getParent() dropped, there are no chance // to figure out node coming from MPSModuleRepository is visible in ProjectRepository // (EditorComponent.editNode() passes here project's repository // but node might come from an MPSModuleRepository (e.g. temp node from console), and they don't // match. // Here, assume node is accessible even if repositories are different if its module is identical // in both. inRepository.getModelAccess().checkReadAccess(); return model.getModule() == inRepository.getModule(model.getModule().getModuleId()); }
public void execute(final EditorContext context) { LOG.assertInCommand(); final EditorComponent editorComponent = (EditorComponent) context.getEditorComponent(); EditorCell pasteTargetCell = getCellToPasteTo(editorComponent.getSelectedCell()); final CellInfo pasteTargetCellInfo = pasteTargetCell.getCellInfo(); final SNode nodeSelected = pasteTargetCell.getSNode(); final SNodePointer selectedNodePointer = new SNodePointer(nodeSelected); final SModel model = nodeSelected.getModel(); // sometimes model is not in repository (paste in merge dialog) final boolean inRepository = model.getModelDescriptor() == selectedNodePointer.getModel(); PasteNodeData data = CopyPasteUtil.getPasteNodeDataFromClipboard(model); if (data == null || data.getNodes().isEmpty()) { data = CopyPasteUtil.getConvertedFromClipboard( model, context.getOperationContext().getProject()); if (data == null || data.getNodes().isEmpty()) return; } final PasteNodeData pasteNodeData = data; SwingUtilities.invokeLater( new Runnable() { public void run() { final Runnable addImportsRunnable = CopyPasteUtil.addImportsWithDialog( pasteNodeData, model, context.getOperationContext()); ModelAccess.instance() .runCommandInEDT( new Runnable() { public void run() { if (addImportsRunnable != null) { addImportsRunnable.run(); } SNode selectedNode = inRepository ? selectedNodePointer.getNode() : nodeSelected; if (jetbrains.mps.util.SNodeOperations.isDisposed(selectedNode)) { StringBuilder errorText = new StringBuilder( "Selected node is disposed: " + selectedNode.toString()); SModelReference modelReference = selectedNodePointer.getModelReference(); if (modelReference != null) { SModelDescriptor modelDescriptor = SModelRepository.getInstance().getModelDescriptor(modelReference); if (modelDescriptor != null) { SModel sModel = modelDescriptor.getSModel(); errorText.append(", sModel.isDisposed(): " + sModel.isDisposed()); SNode node = sModel.getNodeById(selectedNodePointer.getNodeId()); if (node != null) { errorText.append( ", node != null, node.isDisposed(): " + jetbrains.mps.util.SNodeOperations.isDisposed(node)); } else { errorText.append(", node == null"); } } } LOG.error(errorText.toString()); return; } EditorCell selectedCell = pasteTargetCellInfo.findCell(editorComponent); assert selectedCell != null; List<SNode> pasteNodes = pasteNodeData.getNodes(); if (canPasteBefore(selectedCell, pasteNodes)) { new NodePaster(pasteNodes) .pasteRelative(selectedNode, PastePlaceHint.BEFORE_ANCHOR); } else { new NodePaster(pasteNodes).paste(selectedCell); } Set<SReference> requireResolveReferences = new HashSet<SReference>(); for (SReference ref : pasteNodeData.getRequireResolveReferences()) { // ref can be detached from model while using copy/paste handlers if (ref.getSourceNode() == null || ref.getSourceNode().getModel() == null) continue; requireResolveReferences.add(ref); } ResolverComponent.getInstance() .resolveScopesOnly( requireResolveReferences, context.getOperationContext()); // set selection editorComponent.flushEvents(); EditorCell nodeCell = editorComponent.findNodeCell(pasteNodes.get(0)); if (nodeCell == null) return; // after 'set reference'? EditorCell_Label labelCell = nodeCell.findChild(CellFinders.byClass(EditorCell_Label.class, true)); if (labelCell != null) { editorComponent.changeSelection(labelCell); } if (pasteNodes.size() == 1) { editorComponent.pushSelection(nodeCell); } else { SNode firstNodeToSelect = pasteNodes.get(0); SNode lastNodeToSelect = null; for (int i = pasteNodes.size() - 1; i > 0 && lastNodeToSelect == null; i--) { if (pasteNodes.get(i).getParent() == firstNodeToSelect.getParent()) { lastNodeToSelect = pasteNodes.get(i); } } if (lastNodeToSelect != null) { SelectionManager selectionManager = editorComponent.getSelectionManager(); selectionManager.pushSelection( selectionManager.createRangeSelection( firstNodeToSelect, lastNodeToSelect)); } } } }, context.getOperationContext().getProject()); } }); }
public void editNode(final SNode node, final IOperationContext context, final boolean focus) { ModelAccess.assertLegalWrite(); NavigationSupport.getInstance() .openNode(context, node, focus, !(node.getModel() != null && node.getModel().isRoot(node))); }
private static List<INodeSubstituteAction> createActions_internal( SNode parentNode, SNode currentChild, SNode childConcept, IChildNodeSetter childSetter, IOperationContext context) { List<INodeSubstituteAction> resultActions = new ArrayList<INodeSubstituteAction>(); if (childConcept == null) { return resultActions; } // special case if (childConcept == SModelUtil.getBaseConcept()) { if ((currentChild == null || currentChild.getConcept().getId().equals(SNodeUtil.concept_BaseConcept))) { resultActions = new ArrayList<INodeSubstituteAction>(); ISearchScope conceptsSearchScope = SModelSearchUtil.createConceptsFromModelLanguagesScope( parentNode.getModel(), true, context.getScope()); List<SNode> allVisibleConcepts = conceptsSearchScope.getNodes(); for (final SNode visibleConcept : allVisibleConcepts) { resultActions.add( new DefaultChildNodeSubstituteAction( visibleConcept, parentNode, currentChild, childSetter, context.getScope()) { public String getMatchingText(String pattern) { return getMatchingText(pattern, true, true); } public String getVisibleMatchingText(String pattern) { return getMatchingText(pattern); } public String getDescriptionText(String pattern) { String fqName = NameUtil.nodeFQName(visibleConcept); return "lang: " + NameUtil.compactNamespace(NameUtil.namespaceFromConceptFQName(fqName)); } public Icon getIconFor(String pattern) { return getIconFor(pattern, true); } }); } return resultActions; } // pretend we are going to substitute more concrete concept childConcept = ChildSubstituteActionsUtil.getRefinedChildConcept(currentChild); } Language primaryLanguage = SModelUtil.getDeclaringLanguage(childConcept); if (primaryLanguage == null) { LOG.error( "Couldn't build actions : couldn't get declaring language for concept " + org.jetbrains.mps.openapi.model.SNodeUtil.getDebugText(childConcept)); return resultActions; } List<SNode> allBuilders = ChildSubstituteActionsUtil.getActionsBuilders( parentNode, currentChild, childConcept, childSetter, context); if (!ChildSubstituteActionsUtil.containsRemoveDefaults(allBuilders)) { resultActions.addAll( createPrimaryChildSubstituteActions( parentNode, currentChild, childConcept, childSetter, context)); } for (SNode builder : allBuilders) { List<INodeSubstituteAction> addActions = ChildSubstituteActionsUtil.invokeActionFactory( builder, parentNode, currentChild, childConcept, childSetter, context); resultActions.addAll(addActions); } for (SNode builder : allBuilders) { resultActions = ChildSubstituteActionsUtil.applyActionFilter( builder, resultActions, parentNode, currentChild, childConcept, context); } if (childSetter instanceof DefaultChildNodeSetter || childSetter instanceof AbstractCellMenuPart_ReplaceNode_CustomNodeConcept && currentChild != null) { SNode linkDeclaration; if (childSetter instanceof DefaultChildNodeSetter) { linkDeclaration = ((DefaultChildNodeSetter) childSetter).myLinkDeclaration; } else { linkDeclaration = currentChild.getRoleLink(); } Iterator<INodeSubstituteAction> it = resultActions.iterator(); while (it.hasNext()) { INodeSubstituteAction action = it.next(); SNode conceptNode = action.getOutputConcept(); if (conceptNode == null) { continue; } if (!ModelConstraintsManager.canBeParent(parentNode, conceptNode, linkDeclaration, context) || !ModelConstraintsManager.canBeAncestor(parentNode, conceptNode, context)) { it.remove(); } } } return resultActions; }