/*
* Copyright 2003-2011 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.lang.editor.cellProviders;
import jetbrains.mps.editor.runtime.impl.cellActions.CommentUtil;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.AttributeOperations;
import jetbrains.mps.nodeEditor.cellMenu.DefaultSChildSubstituteInfo;
import jetbrains.mps.nodeEditor.cellProviders.AbstractCellListHandler;
import jetbrains.mps.nodeEditor.cells.EditorCell_Constant;
import jetbrains.mps.openapi.editor.EditorContext;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.util.IterableUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.model.SNode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public abstract class SChildListHandler extends AbstractCellListHandler {
private final SNode myNode;
protected SContainmentLink myLink;
private boolean myIsReverseOrder = false;
public SChildListHandler(final SNode ownerNode, final SContainmentLink link, EditorContext editorContext) {
super(link.getRoleName(), editorContext);
myNode = ownerNode;
myLink = link;
}
public SChildListHandler(SNode ownerNode, SContainmentLink link, EditorContext editorContext, boolean isReverseOrder) {
this(ownerNode, link, editorContext);
myIsReverseOrder = isReverseOrder;
}
@NotNull
@Override
public SNode getNode() {
return myNode;
}
@Override
public EditorCell createNodeCell(SNode node) {
return getUpdateSession().updateChildNodeCell(node);
}
@Override
protected EditorCell createEmptyCell() {
EditorCell_Constant emptyCell = new EditorCell_Constant(getEditorContext(), getNode(), null);
emptyCell.setDefaultText("<< ... >>");
emptyCell.setEditable(true);
emptyCell.setSubstituteInfo(new DefaultSChildSubstituteInfo(getNode(), myLink, getEditorContext()));
emptyCell.setRole(getElementRole());
emptyCell.setCellId("empty_" + getElementRole());
return emptyCell;
}
@Override
protected SNode getAnchorNode(EditorCell anchorCell) {
SNode anchorNode = (anchorCell != null ? anchorCell.getSNode() : null);
if (anchorNode != null) {
Collection<? extends SNode> listElements1 = IterableUtil.asCollection(getNode().getChildren(myLink));
// anchor should be directly referenced from "list owner"
while (anchorNode != null && !listElements1.contains(anchorNode)) {
anchorNode = anchorNode.getParent();
}
}
return anchorNode;
}
@Override
protected void doInsertNode(SNode nodeToInsert, SNode anchorNode, boolean insertBefore) {
insertBefore = insertBefore != myIsReverseOrder;
getNode().insertChildBefore(getElementRole(), nodeToInsert,
insertBefore ? anchorNode : anchorNode == null ? getNode().getFirstChild() : anchorNode.getNextSibling());
}
@Override
protected List<SNode> getNodesForList() {
List<SNode> resultList = new ArrayList<SNode>();
Iterable<SNode> nodesAndComments = AttributeOperations.getChildNodesAndAttributes(getNode(), myLink);
if (!myIsReverseOrder) {
resultList.addAll(IterableUtil.asCollection(nodesAndComments));
} else {
List<? extends SNode> children = IterableUtil.copyToList(nodesAndComments);
Collections.reverse(children);
resultList.addAll(children);
}
Iterator<SNode> it = resultList.iterator();
while (it.hasNext()) {
SNode next = it.next();
SNode nodeToFilter = next;
if (CommentUtil.isComment(next)) {
nodeToFilter = CommentUtil.getCommentedNode(next);
}
if (!filter(nodeToFilter)) {
it.remove();
}
}
return resultList;
}
protected boolean filter(SNode childNode) {
return true;
}
}