public void attach()

in projectional/src/main/java/jetbrains/jetpad/projectional/cell/BaseProjectionalSynchronizer.java [346:562]


  public void attach(SynchronizerContext ctx) {
    myTargetCellList.initList();

    initChildViews();

    myRoleSynchronizer.attach(ctx);

    myTarget.addTrait(new CellTrait() {
      @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()) {
          event.consume(cut());
          return;
        }
        super.onCut(cell, event);
      }

      @Override
      public void onPaste(Cell cell, PasteEvent event) {
        if (canPaste(event.getContent())) {
          paste(event.getContent());
          event.consume();
          return;
        }
        super.onPaste(cell, event);
      }

      private boolean canCopy() {
        return hasItemsToCopy() && (myItemKind != null || itemsToStringSupported());
      }

      private ClipboardContent copy() {
        if (myItemKind != null) {
          return createClipboardContent(itemsToCopy());
        } else if (itemsToStringSupported()) {
          return TextContentHelper.createClipboardContent(itemsToString(itemsToCopy()));
        } else {
          throw new IllegalStateException("canCopy() and copy() are inconsistent");
        }
      }

      private ClipboardContent createClipboardContent(List<SourceItemT> items) {
        final List<SourceItemT> copiedItems = new ArrayList<>();
        for (SourceItemT item : items) {
          copiedItems.add(myCloner.apply(item));
        }
        return new ClipboardContent() {

          @Override
          public boolean isSupported(ContentKind<?> kind) {
            if (Objects.equal(kind, myItemKind)) {
              return copiedItems.size() <= 1;
            }

            return Objects.equal(kind, listOf(myItemKind));
          }

          @Override
          public <T> T get(ContentKind<T> kind) {
            if (Objects.equal(kind, myItemKind)) {
              return (T) myCloner.apply(copiedItems.get(0));
            }

            final List<SourceItemT> result = new ArrayList<>();
            for (SourceItemT item : new ArrayList<>(copiedItems)) {
              result.add(myCloner.apply(item));
            }
            return (T) result;
          }

          @Override
          public String toString() {
            if (itemsToStringSupported()) {
              return itemsToString(copiedItems);
            }
            return super.toString();
          }
        };
      }

      private boolean itemsToStringSupported() {
        return myContentListToString != null || myContentToString != null;
      }

      private String itemsToString(List<SourceItemT> items) {
        if (myContentListToString != null) {
          return myContentListToString.apply(items);
        }
        if (myContentToString != null) {
          return myContentToString.apply(items.get(0));
        }
        throw new IllegalStateException("itemsToStringSupported() and itemsToString() are inconsistent");
      }

      private boolean hasItemsToCopy() {
        return (!getSelectedItems().isEmpty()) || (currentItem() != null);
      }

      private List<SourceItemT> itemsToCopy() {
        final List<SourceItemT> items = new ArrayList<>();
        if (!getSelectedItems().isEmpty()) {
          for (SourceItemT item : getSelectedItems()) {
            items.add(item);
          }
        } else {
          items.add(currentItem());
        }
        return items;
      }

      private boolean canCut() {
        return hasItemsToCopy() && myItemKind != null;
      }

      private ClipboardContent cut() {
        List<SourceItemT> toCopy = itemsToCopy();
        ClipboardContent result = createClipboardContent(toCopy);
        clear(toCopy);
        return result;
      }

      private boolean canPaste(ClipboardContent content) {
        for (ContentKind kind : myContentKinds.keySet()) {
          if (content.isSupported(kind) || (isMultiItemPasteSupported() && content.isSupported(listOf(kind)))) {
            return true;
          }
        }
        if (isMultiItemPasteSupported()) {
          for (ContentKind kind : myListContentKinds.keySet()) {
            if (content.isSupported(kind)) {
              return true;
            }
          }
        }
        return false;
      }

      private void paste(ClipboardContent content) {
        for (ListMap<ContentKind, Function<?, SourceItemT>>.Entry entry : myContentKinds.entrySet()) {
          ContentKind kind = entry.key();
          Function<Object, SourceItemT> fromContent = (Function<Object, SourceItemT>) entry.value();
          if (content.isSupported(entry.key())) {
            SourceItemT item = fromContent.apply(content.get(kind));
            if (item != null) {
              insertItem(item);
            }
            return;
          } else if (isMultiItemPasteSupported() && content.isSupported(listOf(kind))) {
            List<SourceItemT> itemsList = (List<SourceItemT>) fromContent.apply(content.get(listOf(kind)));
            if (itemsList != null) {
              insertItems(itemsList);
            }
            return;
          }
        }
        if (isMultiItemPasteSupported()) {
          for (ListMap<ContentKind, Function<?, List<SourceItemT>>>.Entry entry : myListContentKinds.entrySet()) {
            ContentKind kind = entry.key();
            if (content.isSupported(kind)) {
              Function<Object, List<SourceItemT>> fromContent = (Function<Object, List<SourceItemT>>) entry.value();
              List<SourceItemT> items = fromContent.apply(content.get(kind));
              if (items != null) {
                insertItems(items);
              }
              return;
            }
          }
        }
        throw new IllegalStateException("canPaste() and paste() are inconsistent. Content: " + content);
      }

      @Override
      public void onFocusGained(Cell cell, FocusEvent event) {
        super.onFocusGained(cell, event);
        myForDeletion.set(null);
      }

      @Override
      public void onFocusLost(Cell cell, FocusEvent event) {
        super.onFocusLost(cell, event);
        myForDeletion.set(null);
      }

      @Override
      public void onKeyPressed(Cell cell, KeyEvent event) {
        super.onKeyPressed(cell, event);
        myForDeletion.set(null);
      }

      @Override
      public void onKeyTyped(Cell cell, KeyEvent event) {
        super.onKeyTyped(cell, event);
        myForDeletion.set(null);
      }

      @Override
      public void onMouseClicked(Cell cell, MouseEvent event) {
        super.onMouseClicked(cell, event);
        myForDeletion.set(null);
      }

      @Override
      public void onMousePressed(Cell cell, MouseEvent event) {
        super.onMousePressed(cell, event);
        myForDeletion.set(null);
      }
    });
  }