diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java index 9d14093d2e50..d6af8eec1088 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java @@ -18,7 +18,6 @@ package com.intellij.dvcs.push; import com.intellij.dvcs.repo.Repository; import com.intellij.dvcs.repo.RepositoryManager; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.vcs.AbstractVcs; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +30,8 @@ import java.util.Collection; public abstract class PushSupport { - public static final ExtensionPointName> PUSH_SUPPORT_EP = ExtensionPointName.create("com.intellij.pushSupport"); + public static final ExtensionPointName> PUSH_SUPPORT_EP = + ExtensionPointName.create("com.intellij.pushSupport"); @NotNull public abstract AbstractVcs getVcs(); @@ -63,6 +63,7 @@ public abstract class PushSupport { /** * Parse user input string, and create the valid target for push, * or return null if the target name is not valid. + * * @see #validateSpec(Repository, PushSpec) */ @Nullable @@ -80,8 +81,8 @@ public abstract class PushSupport { } /** - * @return null if push spec are valid for selected repository + * @return null if target is valid for selected repository */ @Nullable - public abstract ValidationInfo validateSpec(@NotNull Repository repository, @NotNull PushSpec spec); + public abstract VcsError validate(@NotNull Repository repository, @Nullable String targetToValidate); } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index c1b54e92fa20..5d6b839e5912 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -38,6 +38,7 @@ import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -76,14 +77,18 @@ public class PushController implements Disposable { @Nullable public ValidationInfo validate() { ValidationInfo validInfo = new ValidationInfo("There are no selected repository to push!"); - for (MyRepoModel model : myView2Model.values()) { + for (Map.Entry entry : myView2Model.entrySet()) { + MyRepoModel model = entry.getValue(); if (model.isSelected()) { //has one or more selected roots - PushSupport support = model.getSupport(); - validInfo = support.validateSpec(model.getRepository(), model.getSpec()); - if (validInfo != null) { - // return first non valid node - return validInfo; + validInfo = null; + RepositoryNode node = entry.getKey(); + PushTarget target = model.getSpec().getTarget(); + //todo add validation for model -> hasErrors, too + if (target == null) { + JComponent editingComponent = myPushLog.startEditNode(node); + return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository()), + editingComponent); } } } @@ -91,6 +96,7 @@ public class PushController implements Disposable { } private void startLoadingCommits() { + //todo should be reworked Map priorityLoading = new HashMap(); Map others = new HashMap(); for (Map.Entry entry : myView2Model.entrySet()) { @@ -152,9 +158,16 @@ public class PushController implements Disposable { repoPanel.addRepoNodeListener(new RepositoryNodeListener() { @Override public void onTargetChanged(String newValue) { - myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue))); + VcsError validationError = support.validate(model.getRepository(), newValue); + if (validationError == null) { + myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue))); + loadCommits(model, repoNode, false); + } + else { + //todo may be should store validation errors in model and get errors during dialog validation + myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), null)); + } myDialog.updateButtons(); - loadCommits(model, repoNode, false); } @Override diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java index 3a2e47cfd048..b07bf9243f8a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java @@ -31,16 +31,14 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; +import javax.swing.tree.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -57,15 +55,13 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { private static final String START_EDITING = "startEditing"; private final ChangesBrowser myChangesBrowser; private final CheckboxTree myTree; - private final CheckedTreeNode myRootNode; private final MyTreeCellRenderer myTreeCellRenderer; public PushLog(Project project, CheckedTreeNode root) { - myRootNode = root; - DefaultTreeModel treeModel = new DefaultTreeModel(myRootNode); - treeModel.nodeStructureChanged(myRootNode); + DefaultTreeModel treeModel = new DefaultTreeModel(root); + treeModel.nodeStructureChanged(root); myTreeCellRenderer = new MyTreeCellRenderer(); - myTree = new CheckboxTree(myTreeCellRenderer, myRootNode) { + myTree = new CheckboxTree(myTreeCellRenderer, root) { public boolean isPathEditable(TreePath path) { return isEditable() && path.getLastPathComponent() instanceof DefaultMutableTreeNode; @@ -217,7 +213,10 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { return tag instanceof EditorTextField; } //if keyboard event - then anEvent will be null =( See BasicTreeUi - Object treeNode = myTree.getAnchorSelectionPath().getLastPathComponent(); + TreePath treePath = myTree.getAnchorSelectionPath(); + //there is no selection path if we start editing during initial validation// + if (treePath == null) return true; + Object treeNode = treePath.getLastPathComponent(); return treeNode instanceof EditableTreeNode; } @@ -277,4 +276,14 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { TREE_CONSTRUCTION_LOCK.writeLock().unlock(); } } + + @Nullable + public JComponent startEditNode(@NotNull TreeNode node) { + TreePath path = TreeUtil.getPathFromRoot(node); + if (!myTree.isEditing()) { + myTree.startEditingAtPath(path); + } + return (JComponent)myTree.getCellEditor() + .getTreeCellEditorComponent(myTree, node, false, false, false, myTree.getRowForPath(path)); + } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java index 129d306fc10e..c1afcdd52839 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java @@ -159,6 +159,8 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel if (bounds != null) { setPreferredSize(new Dimension(tree.getWidth() - bounds.x, bounds.height)); } + myDestBranchTextField.grabFocus(); + myDestBranchTextField.requestFocus(); revalidate(); return this; } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java index aa1cbe4a8d09..b441952f7a43 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java @@ -103,6 +103,11 @@ public class VcsPushDialog extends DialogWrapper { initValidation(); } + @Override + protected boolean postponeValidation() { + return false; + } + private class DvcsPushAction extends AbstractAction implements OptionAction { private Action[] myOptions = new Action[0]; private final boolean myForce; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java index b2c874ec40b3..d2a320297c2f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java @@ -19,7 +19,6 @@ import com.intellij.dvcs.push.*; import com.intellij.dvcs.repo.Repository; import com.intellij.dvcs.repo.RepositoryManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.util.Function; @@ -104,9 +103,7 @@ public class HgPushSupport extends PushSupport { @Override @Nullable - public ValidationInfo validateSpec(@NotNull Repository repository, @NotNull PushSpec spec) { - PushTarget target = spec.getTarget(); - return (target == null || StringUtil.isEmptyOrSpaces(target.getPresentation())) ? new ValidationInfo( - "Please, specify remote push path for selected repos!") : null; + public VcsError validate(@NotNull Repository repository, @Nullable String targetToValidate) { + return StringUtil.isEmptyOrSpaces(targetToValidate) ? new VcsError("Please, specify remote push path for repository!") : null; } }