in hybrid/src/main/java/jetbrains/jetpad/hybrid/BaseHybridSynchronizer.java [190:371]
private CellTrait createTargetTrait() {
return new CellTrait() {
@Override
public Object get(Cell cell, CellTraitPropertySpec<?> spec) {
if (spec == HYBRID_SYNCHRONIZER) {
return BaseHybridSynchronizer.this;
}
if (spec == CellStateHandler.PROPERTY) {
return getCellStateHandler();
}
return super.get(cell, spec);
}
@Override
public void onKeyPressed(Cell cell, KeyEvent event) {
Cell focusedCell = cell.getContainer().focusedCell.get();
if (myTargetList.contains(focusedCell)) {
Cell currentCell = cell.getContainer().focusedCell.get();
if (!hasSelection()) {
if (event.is(KeyStrokeSpecs.SELECT_UP) && currentCell != null) {
mySelectionSupport.select(currentCell, currentCell);
event.consume();
}
} else {
Range<Integer> currentRange = selection();
if (event.is(KeyStrokeSpecs.SELECT_UP)) {
ParseNode parseNode = myTokenListEditor.getParseNode();
if (parseNode != null) {
if (!currentRange.equals(parseNode.getRange())) {
ParseNode node = ParseNodes.findForRange(parseNode, currentRange);
ParseNode parentNode = ParseNodes.nonSameRangeParent(node);
if (parentNode != null) {
select(parentNode.getRange());
event.consume();
}
}
} else {
if (!currentRange.equals(Range.closed(0, tokens().size()))) {
select(Range.closed(0, tokens().size()));
event.consume();
}
}
}
if (event.is(KeyStrokeSpecs.SELECT_DOWN)) {
ParseNode parseNode = myTokenListEditor.getParseNode();
if (parseNode != null) {
ParseNode node = ParseNodes.findForRange(parseNode, currentRange);
ParseNode childNode = ParseNodes.nonSameRangeChild(node, myTargetList.indexOf(mySelectionSupport.currentCell()));
if (childNode != null) {
select(childNode.getRange());
event.consume();
return;
}
}
if (!mySelectionSupport.isCurrentCompletelySelected()) {
mySelectionSupport.clearSelection();
event.consume();
}
}
}
}
super.onKeyPressed(cell, event);
}
@Override
public void onCopy(Cell cell, CopyCutEvent event) {
if (canCopy()) {
event.consume(copy());
return;
}
super.onCopy(cell, event);
}
@Override
public void onCut(Cell cell, CopyCutEvent event) {
if (canCut()) {
ClipboardContent content = cut();
myTokensEditPostProcessor.afterTokensEdit(tokens(), property().get());
event.consume(content);
return;
}
super.onCut(cell, event);
}
@Override
public void onPaste(Cell cell, PasteEvent event) {
if (canPaste(event.getContent())) {
paste(event.getContent());
myTokensEditPostProcessor.afterTokensEdit(tokens(), property().get());
event.consume();
return;
}
super.onPaste(cell, event);
}
private boolean canPaste(ClipboardContent content) {
return content.isSupported(TOKENS_CONTENT);
}
private void paste(ClipboardContent content) {
List<Token> tokens = content.get(TOKENS_CONTENT);
Cell currentCell = mySelectionSupport.currentCell();
int targetIndex;
if (currentCell != null) {
int currentCellIndex = myTargetList.indexOf(currentCell);
boolean home = Positions.isHomePosition(currentCell);
boolean end = Positions.isEndPosition(currentCell);
if (home && end) {
// One-char token which allows editing at only one side
if (currentCell instanceof TextTokenCell && ((TextTokenCell) currentCell).noSpaceToLeft()) {
targetIndex = currentCellIndex + 1;
} else {
targetIndex = currentCellIndex;
}
} else if (home) {
targetIndex = currentCellIndex;
} else {
targetIndex = currentCellIndex + 1;
}
} else {
targetIndex = 0;
}
myTokenListEditor.tokens.addAll(targetIndex, tokens);
myTokenListEditor.updateToPrintedTokens();
tokenOperations().select(targetIndex + tokens.size() - 1, LAST).run();
}
private boolean canCopy() {
return hasSelection();
}
private ClipboardContent copy() {
final Range<Integer> selection = selection();
final List<Token> copiedTokens = new ArrayList<>(selection.upperEndpoint() - selection.lowerEndpoint());
for (Token token : tokens().subList(selection.lowerEndpoint(), selection.upperEndpoint())) {
copiedTokens.add(token.copy());
}
return new ClipboardContent() {
@Override
public boolean isSupported(ContentKind<?> kind) {
return kind == TOKENS_CONTENT;
}
@Override
public <T> T get(ContentKind<T> kind) {
if (kind == TOKENS_CONTENT) {
List<Token> result = new ArrayList<>(copiedTokens.size());
for (Token token : copiedTokens) {
result.add(token.copy());
}
return (T) Collections.unmodifiableList(result);
}
return null;
}
@Override
public String toString() {
try {
return TokenUtil.getText(copiedTokens);
} catch (UnsupportedOperationException e) {
return super.toString();
}
}
};
}
private boolean canCut() {
return hasSelection();
}
private ClipboardContent cut() {
ClipboardContent result = copy();
clearSelection();
return result;
}
};
}