private JScrollPane createTable(final MutableTreeNode myTreeRoot) {
    ColumnInfo[] columnInfos = {new ClassColumnInfo(), new PropertyTypeColumnInfo()};

    myTreeTableModel = new ListTreeTableModelOnColumns(myTreeRoot, columnInfos);

    myTreeTable = new MyTreeTable(myTreeTableModel);

    TreeTableSpeedSearch.installOn(myTreeTable, o -> {
      final Object node = o.getLastPathComponent();
      if (node instanceof DefaultMutableTreeNode) {
        final Object object = ((DefaultMutableTreeNode)node).getUserObject();
        if (object instanceof DNamedElement) {
          return ((DNamedElement)object).getName();
        }
      }
      return "";
    });

    PopupHandler.installPopupMenu(myTreeTable, new DefaultActionGroup(new RemoveDynamicAction()), "DynamicToolWindowWrapperPopup");

    final MyColoredTreeCellRenderer treeCellRenderer = new MyColoredTreeCellRenderer();

    myTreeTable.setDefaultRenderer(String.class, new TableCellRenderer() {
      @Override
      public Component getTableCellRendererComponent(JTable table,
                                                     Object value,
                                                     boolean isSelected,
                                                     boolean hasFocus,
                                                     int row,
                                                     int column) {
        if (value instanceof String) {
          try {
            final PsiType type = JavaPsiFacade.getElementFactory(myProject).createTypeFromText((String)value, null);
            String shortName = type.getPresentableText();
            return new JLabel(shortName);
          }
          catch (IncorrectOperationException e) {
            LOG.debug("Type cannot be created", e);
          }
          return new JLabel(QuickfixUtil.shortenType((String)value));
        }

        return new JLabel();
      }
    });

    myTreeTable.setTreeCellRenderer(treeCellRenderer);

    myTreeTable.setRootVisible(false);
    myTreeTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

    final MyPropertyTypeCellEditor typeCellEditor = new MyPropertyTypeCellEditor();

    typeCellEditor.addCellEditorListener(new CellEditorListener() {
      @Override
      public void editingStopped(ChangeEvent e) {
        final TreeTableTree tree = getTree();

        String newTypeValue = ((MyPropertyTypeCellEditor)e.getSource()).getCellEditorValue();

        if (tree == null) {
          myTreeTable.editingStopped(e);
          return;
        }

        try {
          final PsiType type = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(newTypeValue, null);
          newTypeValue = type.getCanonicalText();
        }
        catch (IncorrectOperationException ex) {
          //do nothing in case bad string is entered
        }

        final TreePath editingTypePath = tree.getSelectionPath();
        if (editingTypePath == null) return;

        final TreePath editingClassPath = editingTypePath.getParentPath();

        Object oldTypeValue = myTreeTable.getValueAt(tree.getRowForPath(editingTypePath), TYPE_COLUMN);

        if (!(oldTypeValue instanceof String)) {
          myTreeTable.editingStopped(e);
          return;
        }

        final Object editingPropertyObject = myTreeTable.getValueAt(tree.getRowForPath(editingTypePath), CLASS_OR_ELEMENT_NAME_COLUMN);
        final Object editingClassObject = myTreeTable.getValueAt(tree.getRowForPath(editingClassPath), CLASS_OR_ELEMENT_NAME_COLUMN);

        if (!(editingPropertyObject instanceof DItemElement dynamicElement) || !(editingClassObject instanceof DClassElement)) {
          myTreeTable.editingStopped(e);
          return;
        }

        final String name = dynamicElement.getName();
        final String className = ((DClassElement)editingClassObject).getName();

        if (dynamicElement instanceof DPropertyElement) {
          DynamicManager.getInstance(myProject).replaceDynamicPropertyType(className, name, (String)oldTypeValue, newTypeValue);
        }
        else if (dynamicElement instanceof DMethodElement) {
          final List<ParamInfo> myPairList = ((DMethodElement)dynamicElement).getPairs();
          DynamicManager.getInstance(myProject).replaceDynamicMethodType(className, name, myPairList, (String)oldTypeValue, newTypeValue);
        }
      }

      @Override
      public void editingCanceled(ChangeEvent e) {
        myTreeTable.editingCanceled(e);
      }
    });

    RefactoringListenerManager.getInstance(myProject).addListenerProvider(new RefactoringElementListenerProvider() {
      @Override
      @Nullable
      public RefactoringElementListener getListener(final PsiElement element) {
        if (element instanceof PsiClass) {
          final String qualifiedName = ((PsiClass)element).getQualifiedName();

          return new RefactoringElementListener() {
            @Override
            public void elementMoved(@NotNull PsiElement newElement) {
              renameElement(qualifiedName, newElement);
            }

            @Override
            public void elementRenamed(@NotNull PsiElement newElement) {
              renameElement(qualifiedName, newElement);
            }

            private void renameElement(String oldClassName, PsiElement newElement) {
              if (newElement instanceof PsiClass) {
                final String newClassName = ((PsiClass)newElement).getQualifiedName();

                final DRootElement rootElement = DynamicManager.getInstance(myProject).getRootElement();
                final DClassElement oldClassElement = rootElement.getClassElement(oldClassName);
                final TreeNode oldClassNode = TreeUtil.findNodeWithObject((DefaultMutableTreeNode)myTreeRoot, oldClassElement);

                DynamicManager.getInstance(myProject).replaceClassName(oldClassElement, newClassName);
                myTreeTableModel.nodeChanged(oldClassNode);
              }
            }
          };
        }
        return null;
      }
    });

    myTreeTable.setDefaultEditor(String.class, typeCellEditor);

    myTreeTable.registerKeyboardAction(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        final int selectionRow = myTreeTable.getTree().getLeadSelectionRow();
        myTreeTable.editCellAt(selectionRow, CLASS_OR_ELEMENT_NAME_COLUMN, event);
      }
    }, KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), JComponent.WHEN_FOCUSED);

    myTreeTable.registerKeyboardAction(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        final int selectionRow = myTreeTable.getTree().getLeadSelectionRow();
        myTreeTable.editCellAt(selectionRow, TYPE_COLUMN, event);
      }
    }, KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);

    myTreeTable.getTree().setShowsRootHandles(true);
    myTreeTable.getTableHeader().setReorderingAllowed(false);

    myTreeTable.setVisibleRowCount(10);
    myTreeTable.getColumn(myColumnNames[CLASS_OR_ELEMENT_NAME_COLUMN]).setPreferredWidth(200);
    myTreeTable.getColumn(myColumnNames[TYPE_COLUMN]).setPreferredWidth(160);

    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTreeTable);

    scrollPane.setPreferredSize(JBUI.size(600, 400));
    return scrollPane;
  }
private JScrollPane createTable(final MutableTreeNode myTreeRoot)