/** @return create dialog result object basing on the dialog state */
 private Result createResult() {
   Result rc = new Result();
   String name = myNameTextField.getText().trim();
   if (myTarget == null) {
     rc.target = myConfig.createConfiguration(name);
   } else {
     rc.target = myTarget;
     rc.target.setName(name);
   }
   rc.changes = new ArrayList<Change>(myChangesTree.getIncludedChanges());
   for (BranchDescriptor d : myBranches) {
     if (d.root != null) {
       if (!StringUtil.isEmpty(d.newBranchName)) {
         final String ref = d.referenceToCheckout.trim();
         rc.referencesToUse.put(d.root, Pair.create(ref, d.referencesToSelect.contains(ref)));
         rc.target.setReference(d.root.getPath(), d.newBranchName.trim());
         rc.checkoutNeeded.add(d.root);
       } else {
         String ref = d.referenceToCheckout.trim();
         if (!d.referencesToSelect.contains(ref)) {
           ref = myConfig.detectTag(d.root, ref);
         }
         rc.target.setReference(d.root.getPath(), ref);
         if (!d.referenceToCheckout.equals(d.currentReference)) {
           rc.checkoutNeeded.add(d.root);
         }
       }
     }
   }
   return rc;
 }
 /**
  * Prepare branches for the case of remote checkout
  *
  * @param remoteBranch the remote branch to checkout
  * @param roots the collection of vcs roots
  * @return the list of descriptors for the remote
  * @throws VcsException if failed
  */
 private List<BranchDescriptor> prepareBranchesForRemote(
     String remoteBranch, List<VirtualFile> roots) throws VcsException {
   assert roots.size() > 0;
   List<BranchDescriptor> rc = new ArrayList<BranchDescriptor>();
   HashSet<String> allBranches = new HashSet<String>();
   allBranches.addAll(myConfig.getConfigurationNames());
   final String qualifiedBranch = "remotes/" + remoteBranch;
   String firstRemote = remoteBranch.endsWith("/HEAD") ? null : qualifiedBranch;
   for (VirtualFile root : roots) {
     BranchDescriptor d = new BranchDescriptor();
     d.root = root;
     d.currentReference = myConfig.describeRoot(root);
     if (firstRemote == null) {
       firstRemote = resolveHead(qualifiedBranch, d.root.getPath());
     }
     d.referenceToCheckout = qualifiedBranch;
     Branch.listAsStrings(myProject, root, false, true, d.existingBranches, null);
     Branch.listAsStrings(myProject, root, true, true, d.referencesToSelect, null);
     allBranches.addAll(d.existingBranches);
     rc.add(d);
   }
   String candidate;
   if (firstRemote == null) {
     candidate = "untitled";
   } else {
     int p = firstRemote.indexOf('/', REMOTES_PREFIX.length() + 1);
     assert p > 0 && p < firstRemote.length() - 1
         : "Unexpected format for remote branch: " + firstRemote;
     candidate = firstRemote.substring(p + 1);
   }
   String actual = null;
   if (!allBranches.contains(candidate)) {
     actual = candidate;
   } else {
     for (int i = 2; i < Integer.MAX_VALUE; i++) {
       String t = candidate + i;
       if (!allBranches.contains(t)) {
         actual = t;
         break;
       }
     }
     assert actual != null : "Unexpected number of branches: " + remoteBranch;
   }
   for (BranchDescriptor d : rc) {
     d.newBranchName = actual;
     d.updateStatus();
   }
   return rc;
 }
 /**
  * Prepare branch descriptors for existing configuration
  *
  * @param target the target
  * @param roots the vcs root
  * @return the list of branch descriptors
  * @throws VcsException in case of error
  */
 private List<BranchDescriptor> prepareBranchDescriptors(
     BranchConfiguration target, List<VirtualFile> roots) throws VcsException {
   Map<String, String> map =
       target == null ? Collections.<String, String>emptyMap() : target.getReferences();
   List<BranchDescriptor> rc = new ArrayList<BranchDescriptor>();
   for (VirtualFile root : roots) {
     BranchDescriptor d = new BranchDescriptor();
     d.root = root;
     d.storedReference = map.remove(root.getPath());
     if (d.storedReference != null) {
       d.storedRoot = d.root.getPath();
     }
     d.currentReference = myConfig.describeRoot(root);
     if (d.storedReference != null && !myModify) {
       d.referenceToCheckout = d.storedReference;
     } else {
       d.referenceToCheckout = d.currentReference;
     }
     Branch.listAsStrings(myProject, root, false, true, d.existingBranches, null);
     Branch.listAsStrings(myProject, root, true, true, d.referencesToSelect, null);
     d.updateStatus();
     rc.add(d);
   }
   for (Map.Entry<String, String> m : map.entrySet()) {
     String root = m.getKey();
     String ref = m.getValue();
     BranchDescriptor d = new BranchDescriptor();
     d.storedReference = ref;
     d.storedRoot = root;
     d.referenceToCheckout = ref;
     d.updateStatus();
     rc.add(d);
   }
   return rc;
 }
  /**
   * The constructor
   *
   * @param project the project
   * @param target the target configuration
   * @param allChanges the all changes
   * @param roots the collection of roots
   * @param remoteBranch the remote branch
   * @param config the configuration
   * @param isModify the modify flag
   * @throws VcsException if there is a problem with detecting the current state
   */
  protected SwitchBranchesDialog(
      Project project,
      final BranchConfiguration target,
      final List<Change> allChanges,
      List<VirtualFile> roots,
      String remoteBranch,
      final BranchConfigurations config,
      boolean isModify)
      throws VcsException {
    super(project, true);
    setTitle(isModify ? "Modify Branch Configuration" : "Checkout Branch Configuration");
    assert (remoteBranch == null) || (target == null)
        : "There should be no target for remote branch";
    myTarget = target;
    myConfig = config;
    myModify = isModify;
    myProject = project;
    VirtualFile baseDir = project.getBaseDir();
    myBaseFile = baseDir == null ? null : new File(baseDir.getPath());
    myExistingConfigNames = myConfig.getConfigurationNames();
    myChangesTree =
        new ChangesTreeList<Change>(
            myProject,
            Collections.<Change>emptyList(),
            !myModify,
            true,
            null,
            RemoteRevisionsCache.getInstance(project).getChangesNodeDecorator()) {
          protected DefaultTreeModel buildTreeModel(
              final List<Change> changes, ChangeNodeDecorator changeNodeDecorator) {
            TreeModelBuilder builder = new TreeModelBuilder(myProject, false);
            return builder.buildModel(changes, changeNodeDecorator);
          }

          protected List<Change> getSelectedObjects(final ChangesBrowserNode<Change> node) {
            return node.getAllChangesUnder();
          }

          @Nullable
          protected Change getLeadSelectedObject(final ChangesBrowserNode node) {
            final Object o = node.getUserObject();
            if (o instanceof Change) {
              return (Change) o;
            }
            return null;
          }
        };
    if (remoteBranch != null) {
      myBranches = prepareBranchesForRemote(remoteBranch, roots);
    } else {
      myBranches = prepareBranchDescriptors(target, roots);
    }
    Collections.sort(
        myBranches,
        new Comparator<BranchDescriptor>() {
          @Override
          public int compare(BranchDescriptor o1, BranchDescriptor o2) {
            return o1.getRoot().compareTo(o2.getRoot());
          }
        });
    if (target == null) {
      myNameTextField.setText(generateNewConfigurationName());
    } else {
      myNameTextField.setText(target.getName());
    }
    myChangesTree.setChangesToDisplay(allChanges);
    myChangesTree.setIncludedChanges(Collections.<Change>emptyList());
    myChangesPanel.add(myChangesTree, BorderLayout.CENTER);
    myChangesLabel.setLabelFor(myChangesTree);
    if (myModify) {
      myChangesLabel.setText("Changes in the current configuration");
    }
    RootTableModel tableModel = new RootTableModel();
    myBranchesTable.setModel(tableModel);
    myBranchesTable.setDefaultRenderer(Pair.class, new PairTableRenderer());
    final TableColumnModel columns = myBranchesTable.getColumnModel();
    final PairTableRenderer renderer = new PairTableRenderer();
    for (Enumeration<TableColumn> cs = columns.getColumns(); cs.hasMoreElements(); ) {
      cs.nextElement().setCellRenderer(renderer);
    }
    TableColumn revisionColumn = columns.getColumn(RootTableModel.REVISION_COLUMN);
    revisionColumn.setCellEditor(new ReferenceEditor());
    TableColumn branchColumn = columns.getColumn(RootTableModel.NEW_BRANCH_COLUMN);
    branchColumn.setCellEditor(new BranchNameEditor());
    myNameTextField
        .getDocument()
        .addDocumentListener(
            new DocumentAdapter() {
              @Override
              protected void textChanged(DocumentEvent e) {
                verify();
              }
            });
    tableModel.addTableModelListener(
        new TableModelListener() {
          @Override
          public void tableChanged(TableModelEvent e) {
            verify();
          }
        });
    verify();
    init();
  }