/*
* Copyright 2003-2013 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.nodeEditor.cells;
import jetbrains.mps.openapi.editor.cells.CellTraversalUtil;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.openapi.editor.cells.EditorCell_Collection;
import jetbrains.mps.util.AndCondition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.util.Condition;
/**
* Semen Alperovich
* 03 15, 2013
*/
public class CellFinderUtil {
// no one can instantiate this class.
private CellFinderUtil() {
}
public enum Finder {
FIRST_ERROR,
LAST_ERROR,
FIRST_SELECTABLE_LEAF,
LAST_SELECTABLE_LEAF,
FIRST_EDITABLE,
LAST_EDITABLE
}
// You can find child by this common method or by specialized methods below
public static EditorCell findChild(@NotNull EditorCell cell, @NotNull Finder finder, boolean includeThis) {
switch (finder) {
case FIRST_ERROR:
return findFirstError(cell, includeThis);
case LAST_ERROR:
return findLastError(cell, includeThis);
case FIRST_EDITABLE:
return findFirstEditable(cell, includeThis);
case LAST_EDITABLE:
return findLastEditable(cell, includeThis);
case FIRST_SELECTABLE_LEAF:
return findFirstSelectableLeaf(cell, includeThis);
case LAST_SELECTABLE_LEAF:
return findLastSelectableLeaf(cell, includeThis);
default:
return null;
}
}
public static EditorCell findChild(@NotNull EditorCell cell, @NotNull Finder finder) {
return findChild(cell, finder, false);
}
public static EditorCell findChildByManyFinders(@NotNull EditorCell cell, boolean includeThis, @NotNull Finder... finders) {
for (Finder finder : finders) {
EditorCell result = findChild(cell, finder, includeThis);
if (result != null) {
return result;
}
}
return null;
}
public static EditorCell findChildByManyFinders(@NotNull EditorCell cell, @NotNull Finder... finders) {
return findChildByManyFinders(cell, false, finders);
}
public static EditorCell_Collection findParent(@NotNull EditorCell cell, @NotNull Condition<EditorCell_Collection> condition) {
if (cell instanceof EditorCell_Collection && condition.met(
((EditorCell_Collection) cell))) {
return ((EditorCell_Collection) cell);
}
for (EditorCell_Collection parent = cell.getParent(); parent != null; parent = parent.getParent()) {
if (condition.met(parent)) {
return parent;
}
}
return null;
}
public static EditorCell findChildByCondition(@NotNull EditorCell cell, @NotNull Condition<EditorCell> condition, boolean forward, boolean includeThis) {
for (EditorCell current : CellTraversalUtil.iterateTree(cell, cell, forward).skipStart(!includeThis)) {
if (condition.met(current)) {
return current;
}
}
return null;
}
public static <C extends EditorCell> C findChildByConditionAndClass(@NotNull EditorCell cell, @NotNull final Condition<EditorCell> condition,
final Class<C> clazz, boolean forward, boolean includeThis) {
return ((C) findChildByCondition(cell, new AndCondition<EditorCell>(new ByClassCondition(clazz), condition), forward, includeThis));
}
public static <C extends EditorCell> C findChildByConditionAndClass(@NotNull EditorCell cell, @NotNull final Condition<EditorCell> condition,
final Class<C> clazz, boolean forward) {
return findChildByConditionAndClass(cell, condition, clazz, forward, false);
}
public static EditorCell findChildByCondition(@NotNull EditorCell cell, @NotNull Condition<EditorCell> condition, boolean forward) {
return findChildByCondition(cell, condition, forward, false);
}
public static <C extends EditorCell> C findChildByClass(@NotNull EditorCell cell, @NotNull final Class<C> clazz, boolean forward, boolean includeThis) {
return ((C) findChildByCondition(cell, new ByClassCondition(clazz), forward, includeThis));
}
public static <C extends EditorCell> C findChildByClass(@NotNull EditorCell cell, @NotNull final Class<C> clazz, boolean forward) {
return findChildByClass(cell, clazz, forward, false);
}
public static EditorCell findChildById(@NotNull EditorCell cell, @NotNull final SNode node, @NotNull final String cellId, boolean includeThis) {
return findChildByCondition(cell, new ByIdCondition(node, cellId), true, includeThis);
}
public static EditorCell findChildById(@NotNull EditorCell cell, @NotNull final SNode node, final String cellId) {
return findChildById(cell, node, cellId, false);
}
private static EditorCell_Label findEditable(@NotNull EditorCell cell, boolean forward, boolean includeThis) {
return findChildByConditionAndClass(cell, jetbrains.mps.openapi.editor.cells.CellConditions.EDITABLE, EditorCell_Label.class, forward, includeThis);
}
public static EditorCell_Label findFirstEditable(@NotNull EditorCell cell, boolean includeThis) {
return findEditable(cell, true, includeThis);
}
public static EditorCell_Label findFirstEditable(@NotNull EditorCell cell) {
return findFirstEditable(cell, false);
}
public static EditorCell_Label findLastEditable(@NotNull EditorCell cell, boolean includeThis) {
return findEditable(cell, false, includeThis);
}
public static EditorCell_Label findLastEditable(@NotNull EditorCell cell) {
return findLastEditable(cell, false);
}
private static EditorCell_Label findError(@NotNull EditorCell cell, boolean forward, boolean includeThis) {
return findChildByConditionAndClass(cell, CellConditions.ERROR_CONDITION, EditorCell_Label.class, forward, includeThis);
}
public static EditorCell_Label findFirstError(@NotNull EditorCell cell, boolean includeThis) {
return findError(cell, true, includeThis);
}
public static EditorCell_Label findFirstError(@NotNull EditorCell cell) {
return findFirstError(cell, false);
}
public static EditorCell_Label findLastError(@NotNull EditorCell cell, boolean includeThis) {
return findError(cell, false, includeThis);
}
public static EditorCell_Label findLastError(@NotNull EditorCell cell) {
return findLastError(cell, false);
}
private static EditorCell findSelectableLeaf(@NotNull EditorCell cell, boolean forward, boolean includeThis) {
return findChildByCondition(cell, jetbrains.mps.openapi.editor.cells.CellConditions.SELECTABLE_lEAF, forward, includeThis);
}
public static EditorCell findFirstSelectableLeaf(@NotNull EditorCell cell, boolean includeThis) {
return findSelectableLeaf(cell, true, includeThis);
}
public static EditorCell findFirstSelectableLeaf(@NotNull EditorCell cell) {
return findFirstSelectableLeaf(cell, false);
}
public static EditorCell findLastSelectableLeaf(@NotNull EditorCell cell, boolean includeThis) {
return findSelectableLeaf(cell, false, includeThis);
}
public static EditorCell findLastSelectableLeaf(@NotNull EditorCell cell) {
return findLastSelectableLeaf(cell, false);
}
private static class ByClassCondition implements Condition<EditorCell> {
private Class myClass;
public ByClassCondition(Class clazz) {
myClass = clazz;
}
@Override
public boolean met(EditorCell cell) {
return myClass.isInstance(cell);
}
}
private static class ByIdCondition implements Condition<EditorCell> {
private SNode myNode;
private String myCellId;
public ByIdCondition(SNode node, String id) {
myNode = node;
myCellId = id;
}
@Override
public boolean met(EditorCell object) {
return object.getSNode() == myNode && myCellId.equals(object.getCellId());
}
}
}