package jetbrains.mps.vcs.diff.ui.common;
/*Generated by MPS */
import jetbrains.mps.nodeEditor.messageTargets.EditorMessageWithTarget;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.vcs.diff.changes.ModelChange;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.errors.messageTargets.MessageTarget;
import jetbrains.mps.openapi.editor.message.EditorMessageOwner;
import jetbrains.mps.errors.MessageStatus;
import java.awt.Color;
import jetbrains.mps.vcs.diff.changes.ChangeType;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.errors.messageTargets.MessageTargetEnum;
import jetbrains.mps.openapi.editor.cells.EditorCell_Collection;
import java.awt.Graphics;
import jetbrains.mps.nodeEditor.EditorComponent;
import java.awt.Rectangle;
import jetbrains.mps.nodeEditor.cells.GeometryUtil;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.nodeEditor.messageTargets.CellFinder;
import jetbrains.mps.nodeEditor.cells.PropertyAccessor;
import jetbrains.mps.nodeEditor.cells.EditorCell_Property;
import jetbrains.mps.openapi.editor.message.SimpleEditorMessage;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.openapi.editor.cells.CellMessagesUtil;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.errors.messageTargets.DeletedNodeMessageTarget;
import jetbrains.mps.ide.util.ColorAndGraphicsUtil;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import jetbrains.mps.smodel.ModelAccess;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import jetbrains.mps.nodeEditor.inspector.InspectorEditorComponent;
import java.util.Iterator;
import jetbrains.mps.baseLanguage.closures.runtime.YieldingIterator;
import jetbrains.mps.util.Computable;
import jetbrains.mps.nodeEditor.cellLayout.CellLayout_Vertical;
import jetbrains.mps.editor.runtime.style.StyleAttributes;
import org.jetbrains.annotations.NotNull;
import org.apache.log4j.Level;
import jetbrains.mps.nodeEditor.cells.ModelAccessor;
public class ChangeEditorMessage extends EditorMessageWithTarget {
private static final Logger LOG = LogManager.getLogger(ChangeEditorMessage.class);
private static final String NAME_PROPERTY = "name";
private ModelChange myChange;
private ChangeEditorMessage.ConflictChecker myConflictsChecker;
private boolean myHighlighted;
protected ChangeEditorMessage(SNode node, MessageTarget target, EditorMessageOwner owner, ModelChange change, ChangeEditorMessage.ConflictChecker conflictChecker, boolean highlighted) {
super(node, MessageStatus.OK, target, null, "", owner);
myChange = change;
myConflictsChecker = conflictChecker;
myHighlighted = highlighted;
}
public boolean isConflicted() {
return myConflictsChecker != null && myConflictsChecker.isChangeConflicted(myChange);
}
@Override
public boolean showInGutter() {
return false;
}
@Override
public Color getColor() {
return ChangeColors.get((isConflicted() ? ChangeType.CONFLICTED : myChange.getType()));
}
public ModelChange getChange() {
return myChange;
}
@Override
public boolean isBackground() {
return true;
}
private boolean isDirectCell(EditorCell cell) {
// Return true if and only if this cell should be painted, not only set in frame
if (cell == null) {
return false;
}
if (myMessageTarget.getTarget() == MessageTargetEnum.NODE) {
return getNode() == cell.getSNode();
} else {
return !(cell instanceof EditorCell_Collection) && isNameCell(cell) == (myMessageTarget.getTarget() == MessageTargetEnum.PROPERTY && NAME_PROPERTY.equals(myMessageTarget.getRole()));
}
}
@Override
public boolean showInEditor() {
return myHighlighted;
}
@Override
public void paint(Graphics graphics, EditorComponent editor, EditorCell cell) {
if (!(myHighlighted)) {
return;
}
if (isDirectCell(cell)) {
((jetbrains.mps.nodeEditor.cells.EditorCell) cell).paintSelection(graphics, getColor(), false);
repaintConflictedMessages(graphics, cell);
} else {
if (myMessageTarget.getTarget() == MessageTargetEnum.DELETED_CHILD) {
drawDeletedChild(graphics, cell);
} else {
Rectangle bounds = (isIndirectRoot(editor) ? getFirstPseudoLineBounds(editor) : GeometryUtil.getBounds(cell));
graphics.setColor(ChangeColors.get((isConflicted() ? ChangeType.CONFLICTED : ChangeType.CHANGE)));
graphics.drawRect(bounds.x + 1, bounds.y + 1, bounds.width - 2, bounds.height - 2);
}
}
}
@Override
public EditorCell getCell(EditorComponent editor) {
EditorCell cell = super.getCell(editor);
if (cell != null && cell.isBig() && !(isDirectCell(cell))) {
SNode node = getNode();
if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept"))) {
cell = CellFinder.getCellForProperty(editor, node, NAME_PROPERTY);
}
}
return cell;
}
@Override
public boolean acceptCell(EditorCell cell, EditorComponent component) {
EditorCell superCell = super.getCell(component);
return isNameCell(cell) && !(isDirectCell(cell)) && superCell != null && cell.isBig() || super.acceptCell(cell, component);
}
private boolean isNameCell(EditorCell cell) {
PropertyAccessor pa = as_myu41h_a0a0a81(check_myu41h_a0a0a71((as_myu41h_a0a0a0a0a81(cell, EditorCell_Property.class))), PropertyAccessor.class);
return getNode() == check_myu41h_a0a1a71(pa) && NAME_PROPERTY.equals(check_myu41h_a0a0b0r(pa));
}
private void repaintConflictedMessages(Graphics graphics, EditorCell cell) {
// This is a workaround for case when any change message is going to be painted over
// "conflicted" red frame. In this case, we repaint conflicted red frame again
EditorCell_Collection parent = cell.getParent();
if (parent != null && parent.getCellsCount() == 1) {
SimpleEditorMessage messageToRepaint = Sequence.fromIterable(((Iterable<ChangeEditorMessage>) CellMessagesUtil.getMessages(parent, ChangeEditorMessage.class))).findFirst(new IWhereFilter<ChangeEditorMessage>() {
public boolean accept(ChangeEditorMessage m) {
return m.isConflicted();
}
});
if (messageToRepaint != null) {
((ChangeEditorMessage) messageToRepaint).paint(graphics, (EditorComponent) cell.getEditorComponent(), parent);
}
}
}
private void drawDeletedChild(Graphics graphics, EditorCell cell) {
if (myMessageTarget.getRole().equals(cell.getRole())) {
int index = ((DeletedNodeMessageTarget) myMessageTarget).getNextChildIndex();
if (index != -1) {
EditorCell_Collection collectionCell = (EditorCell_Collection) cell;
if (hasChildrenWithDifferentNode(cell)) {
EditorCell childCell = getChildCell(collectionCell, index);
if (isVertical(collectionCell)) {
drawHorizontalLine(graphics, collectionCell, childCell);
} else {
drawVerticalLineWithArrows(graphics, collectionCell, childCell);
}
} else {
((jetbrains.mps.nodeEditor.cells.EditorCell) cell).paintSelection(graphics, getColor(), false);
}
}
}
}
private void drawHorizontalLine(Graphics graphics, EditorCell_Collection collectionCell, EditorCell childCell) {
int y;
if (childCell != null) {
y = childCell.getY();
} else {
y = collectionCell.lastCell().getBottom();
}
graphics.setColor(getColor());
graphics.drawLine(collectionCell.getX(), y, collectionCell.getRight(), y);
}
private void drawVerticalLineWithArrows(Graphics graphics, EditorCell_Collection collectionCell, EditorCell cell) {
int x;
EditorCell childCell;
if (cell != null) {
childCell = cell;
x = cell.getX();
} else {
childCell = collectionCell.lastCell();
x = childCell.getRight();
}
int y1 = childCell.getY();
int y2 = childCell.getBottom();
graphics.setColor(getColor());
graphics.drawLine(x, y1, x, y2);
graphics.fillPolygon(new int[]{x, x - 3, x + 3}, new int[]{y1 - 2, y1 - 5, y1 - 5}, 3);
graphics.fillPolygon(new int[]{x, x - 3, x + 3}, new int[]{y2 + 2, y2 + 5, y2 + 5}, 3);
graphics.setColor(ColorAndGraphicsUtil.brightenColor(getColor(), 0.8f));
graphics.drawPolygon(new int[]{x, x - 3, x + 3}, new int[]{y1 - 2, y1 - 5, y1 - 5}, 3);
graphics.drawPolygon(new int[]{x, x - 3, x + 3}, new int[]{y2 + 2, y2 + 5, y2 + 5}, 3);
}
private boolean isIndirectRoot(final EditorComponent editor) {
final Wrappers._boolean res = new Wrappers._boolean();
ModelAccess.instance().runReadAction(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0<Boolean>() {
public Boolean invoke() {
return res.value = !(isDirectCell(getCell(editor))) && check_myu41h_a0a0a0a0a0b0w(getNode(), ChangeEditorMessage.this) == null && !(editor instanceof InspectorEditorComponent);
}
}));
return res.value;
}
private Rectangle getFirstPseudoLineBounds(EditorComponent editor) {
Iterable<EditorCell> leafCells = new _FunctionTypes._return_P1_E0<Iterable<EditorCell>, EditorCell>() {
public Iterable<EditorCell> invoke(final EditorCell cell) {
return new Iterable<EditorCell>() {
public Iterator<EditorCell> iterator() {
return new YieldingIterator<EditorCell>() {
private int __CP__ = 0;
protected boolean moveToNext() {
__loop__:
do {
__switch__:
switch (this.__CP__) {
case -1:
assert false : "Internal error";
return false;
case 4:
this._4_child_it = Sequence.fromIterable((EditorCell_Collection) cell).iterator();
case 5:
if (!(this._4_child_it.hasNext())) {
this.__CP__ = 1;
break;
}
this._4_child = this._4_child_it.next();
this.__CP__ = 6;
break;
case 7:
this._7__yield_myu41h_a0a0a0a0a0a32_it = Sequence.fromIterable(invoke(_4_child)).iterator();
case 8:
if (!(this._7__yield_myu41h_a0a0a0a0a0a32_it.hasNext())) {
this.__CP__ = 5;
break;
}
this._7__yield_myu41h_a0a0a0a0a0a32 = this._7__yield_myu41h_a0a0a0a0a0a32_it.next();
this.__CP__ = 9;
break;
case 2:
if (cell instanceof EditorCell_Collection) {
this.__CP__ = 3;
break;
}
this.__CP__ = 11;
break;
case 10:
this.__CP__ = 8;
this.yield(_7__yield_myu41h_a0a0a0a0a0a32);
return true;
case 12:
this.__CP__ = 1;
this.yield(cell);
return true;
case 0:
this.__CP__ = 2;
break;
case 3:
this.__CP__ = 4;
break;
case 6:
this.__CP__ = 7;
break;
case 9:
this.__CP__ = 10;
break;
case 11:
this.__CP__ = 12;
break;
default:
break __loop__;
}
} while (true);
return false;
}
private EditorCell _4_child;
private Iterator<EditorCell> _4_child_it;
private EditorCell _7__yield_myu41h_a0a0a0a0a0a32;
private Iterator<EditorCell> _7__yield_myu41h_a0a0a0a0a0a32_it;
};
}
};
}
}.invoke(editor.getRootCell());
if (Sequence.fromIterable(leafCells).first() == null) {
return new Rectangle();
}
final int firstCellY = Sequence.fromIterable(leafCells).first().getY();
return GeometryUtil.getBounds(Sequence.fromIterable(leafCells).where(new IWhereFilter<EditorCell>() {
public boolean accept(EditorCell it) {
return it.getY() == firstCellY;
}
}).toGenericArray(EditorCell.class));
}
public Bounds getBounds(final EditorComponent editor) {
if (myMessageTarget.getTarget() != MessageTargetEnum.DELETED_CHILD) {
if (isIndirectRoot(editor)) {
Rectangle r = getFirstPseudoLineBounds(editor);
return new Bounds(r.y, r.y + r.height);
} else {
return getBoundsSuper(editor);
}
} else {
DeletedNodeMessageTarget cmt = ((DeletedNodeMessageTarget) myMessageTarget);
EditorCell cell = ModelAccess.instance().runReadAction(new Computable<EditorCell>() {
public EditorCell compute() {
return getCell(editor);
}
});
if (cell == null) {
return new Bounds(-1, -1);
}
if (cmt.getRole().equals(cell.getRole())) {
if (hasChildrenWithDifferentNode(cell)) {
return getBoundsForChild((EditorCell_Collection) cell, cmt.getNextChildIndex());
} else {
return getBoundsSuper(editor);
}
} else {
int y = cell.getY();
return new Bounds(y, y + 1);
}
}
}
private Bounds getBoundsForChild(EditorCell_Collection cell, int index) {
EditorCell childCell = getChildCell(cell, index);
int minY;
int maxY;
if (childCell == null) {
EditorCell lastCell = cell.lastCell();
minY = (isVertical(cell) ? lastCell.getBottom() : lastCell.getY());
maxY = Math.max(lastCell.getBottom(), minY + 1);
} else {
minY = childCell.getY();
maxY = (isVertical(cell) ? minY + 1 : childCell.getBottom());
}
return new Bounds(minY, maxY);
}
private Bounds getBoundsSuper(EditorComponent component) {
return new Bounds(super.getStart(component), super.getStart(component) + super.getHeight(component));
}
@Override
public int getStart(jetbrains.mps.openapi.editor.EditorComponent component) {
return (int) getBounds(((EditorComponent) component)).start();
}
@Override
public int getHeight(jetbrains.mps.openapi.editor.EditorComponent component) {
return getBounds(((EditorComponent) component)).length();
}
public void setHighlighted(boolean highlighted) {
myHighlighted = highlighted;
}
private static boolean hasChildrenWithDifferentNode(EditorCell cell) {
if (cell instanceof EditorCell_Collection) {
final EditorCell_Collection collectionCell = (EditorCell_Collection) cell;
return Sequence.fromIterable(((Iterable<EditorCell>) collectionCell)).any(new IWhereFilter<EditorCell>() {
public boolean accept(EditorCell child) {
return child.getSNode() != collectionCell.getSNode();
}
});
} else {
return false;
}
}
private static boolean isVertical(EditorCell cell) {
return cell instanceof EditorCell_Collection && (((EditorCell_Collection) cell).getCellLayout() instanceof CellLayout_Vertical || cell.getStyle().get(StyleAttributes.INDENT_LAYOUT_CHILDREN_NEWLINE));
}
private static EditorCell getChildCell(@NotNull EditorCell_Collection collectionCell, int nodeIndex) {
if (nodeIndex == -1) {
return null;
}
int currentNodeIndex = -1;
for (EditorCell childCell : collectionCell) {
if (childCell.getSNode() != collectionCell.getSNode()) {
currentNodeIndex++;
}
if (currentNodeIndex == nodeIndex) {
return childCell;
}
}
if (currentNodeIndex == nodeIndex - 1) {
return null;
}
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("Could not find child cell index for deleted child: currentNodeIndex=" + currentNodeIndex + ", total cells=" + collectionCell.getCellsCount() + ", requested nodeIndex=" + nodeIndex);
}
return null;
}
public interface ConflictChecker {
boolean isChangeConflicted(ModelChange change);
}
private static ModelAccessor check_myu41h_a0a0a71(EditorCell_Property checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getModelAccessor();
}
return null;
}
private static SNode check_myu41h_a0a1a71(PropertyAccessor checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getNode();
}
return null;
}
private static String check_myu41h_a0a0b0r(PropertyAccessor checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getPropertyName();
}
return null;
}
private static SNode check_myu41h_a0a0a0a0a0b0w(SNode checkedDotOperand, ChangeEditorMessage checkedDotThisExpression) {
if (null != checkedDotOperand) {
return checkedDotOperand.getParent();
}
return null;
}
private static <T> T as_myu41h_a0a0a81(Object o, Class<T> type) {
return (type.isInstance(o) ? (T) o : null);
}
private static <T> T as_myu41h_a0a0a0a0a81(Object o, Class<T> type) {
return (type.isInstance(o) ? (T) o : null);
}
}