diff --git a/plugins/hg4idea/hg4idea.iml b/plugins/hg4idea/hg4idea.iml index b8677676d493..994b8de42483 100644 --- a/plugins/hg4idea/hg4idea.iml +++ b/plugins/hg4idea/hg4idea.iml @@ -13,6 +13,8 @@ + + diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index 7eed0e136d1a..3471afa949bc 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -21,15 +21,26 @@ hg4idea.error=Error hg4idea.revert=Revert hg4idea.commit=Commit +hg4idea.init.dialog.title=Create Mercurial repository +hg4idea.init.dialog.incorrect.path=The specified path is incorrect +hg4idea.init.dialog.option.create.repository.for.whole.project=&Create repository for the whole project +hg4idea.init.dialog.option.select.folder=&Select where to create repository hg4idea.init.destination.directory.description=Select directory where the new Mercurial repository will be created. hg4idea.init.destination.directory.title=Select directory for hg init -hg4idea.init.error.already.under.hg=The selected directory {0} is already under hg. -hg4idea.init.error.title=hg init Error +hg4idea.init.this.is.hg.root=The selected folder {0} is already a Mercurial root +hg4idea.init.already.under.hg.description=The selected directory {0} is already under Mercurial: {1}
Would you like to create new repository in the selected folder or use the parent one? +hg4idea.init.already.under.hg.title=This directory is already under hg +hg4idea.init.already.under.hg.dialog.title=Directory is under hg +hg4idea.init.already.under.hg.option.create.project.at.parent=Use parent repository and create IDEA project for it. +hg4idea.init.already.under.hg.option.use.parent=Use parent repository, but keep working in this project. +hg4idea.init.already.under.hg.option.create.repo.here=Create new repository here. +hg4idea.init.created.notification.title=Mercurial repository created +hg4idea.init.created.notification.description=Repository was created in {0} hg4idea.clone.title=Clone Mercurial Repostiroy hg4idea.clone.button.clone=Clone hg4idea.clone.button.test=&Test Repository -hg4idea.clone.cloning.repository=Cloning source repository {0} +hg4idea.clone.progress=Cloning source repository {0} hg4idea.clone.error.destination.directory.exists=The path {0} exists. Mercurial cannot clone to existing directory. hg4idea.clone.error.repository.url=Repository URL is a malformed URL or non-existent directory. hg4idea.clone.error.test.failed=Repository test has failed. @@ -40,7 +51,7 @@ hg4idea.clone.parent.directory=&Parent Directory hg4idea.clone.parent.directory.title=Parent Directory hg4idea.clone.parent.directory.description=Select a parent directory destination directory for clone hg4idea.clone.directory.name=Directory &Name -hg4idea.clone.test.testing=Testing repository {0} +hg4idea.clone.test.progress=Testing repository {0} hg4idea.clone.test.success.message=Connection to repository {0} has been successful. hg4idea.clone.test.success=Connection successful diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java index 52b77a2a0d7e..dcb3ce3df2c4 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java @@ -174,4 +174,29 @@ public abstract class HgUtil { } + /** + * Finds the nearest parent directory which is an hg root. + * @param dir Directory which parent will be checked. + * @return Directory which is the nearest hg root being a parent of this directory, + * or null if this directory is not under hg. + * @see com.intellij.openapi.vcs.AbstractVcs#isVersionedDirectory(com.intellij.openapi.vfs.VirtualFile) + */ + @Nullable + public static VirtualFile getNearestHgRoot(VirtualFile dir) { + VirtualFile currentDir = dir; + while (currentDir != null) { + if (isHgRoot(currentDir)) { + return currentDir; + } + currentDir = currentDir.getParent(); + } + return null; + } + + /** + * Checks if the given directory is an hg root. + */ + public static boolean isHgRoot(VirtualFile dir) { + return dir.findChild(".hg") != null; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index 7aafcbc1cb0d..377857fe35d1 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -12,32 +12,49 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.concurrency.*; -import com.intellij.openapi.application.*; -import com.intellij.openapi.fileEditor.*; -import com.intellij.openapi.options.*; -import com.intellij.openapi.project.*; -import com.intellij.openapi.util.*; -import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.annotate.*; -import com.intellij.openapi.vcs.changes.*; -import com.intellij.openapi.vcs.checkin.*; -import com.intellij.openapi.vcs.diff.*; -import com.intellij.openapi.vcs.history.*; -import com.intellij.openapi.vcs.rollback.*; -import com.intellij.openapi.vcs.update.*; -import com.intellij.openapi.vfs.*; -import com.intellij.openapi.wm.*; -import com.intellij.util.messages.*; +import com.intellij.concurrency.JobScheduler; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; +import com.intellij.openapi.fileEditor.FileEditorManagerListener; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.CommittedChangesProvider; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.annotate.AnnotationProvider; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangeProvider; +import com.intellij.openapi.vcs.checkin.CheckinEnvironment; +import com.intellij.openapi.vcs.diff.DiffProvider; +import com.intellij.openapi.vcs.history.VcsHistoryProvider; +import com.intellij.openapi.vcs.rollback.RollbackEnvironment; +import com.intellij.openapi.vcs.update.UpdateEnvironment; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileListener; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.wm.StatusBar; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.messages.Topic; import org.zmlx.hg4idea.provider.*; -import org.zmlx.hg4idea.provider.annotate.*; -import org.zmlx.hg4idea.provider.commit.*; -import org.zmlx.hg4idea.provider.update.*; -import org.zmlx.hg4idea.ui.*; +import org.zmlx.hg4idea.provider.annotate.HgAnnotationProvider; +import org.zmlx.hg4idea.provider.commit.HgCheckinEnvironment; +import org.zmlx.hg4idea.provider.commit.HgCommitExecutor; +import org.zmlx.hg4idea.provider.update.HgIntegrateEnvironment; +import org.zmlx.hg4idea.provider.update.HgUpdateEnvironment; +import org.zmlx.hg4idea.ui.HgChangesetStatus; +import org.zmlx.hg4idea.ui.HgCurrentBranchStatus; import javax.swing.*; import java.io.File; -import java.util.concurrent.*; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; public class HgVcs extends AbstractVcs { @@ -57,6 +74,7 @@ public class HgVcs extends AbstractVcs { public static final String VCS_NAME = "hg4idea"; public static final String DIRSTATE_FILE_PATH = ".hg/dirstate"; + public static final String NOTIFICATION_GROUP_ID = "Mercurial"; private final HgChangeProvider changeProvider; private final HgProjectConfigurable configurable; @@ -196,14 +214,7 @@ public class HgVcs extends AbstractVcs { @Override public boolean isVersionedDirectory(VirtualFile dir) { - VirtualFile currentDir = dir; - while (currentDir != null) { - if (currentDir.findChild(".hg") != null) { - return true; - } - currentDir = currentDir.getParent(); - } - return false; + return HgUtil.getNearestHgRoot(dir) != null; } public boolean isStarted() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgInit.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgInit.java index 5dae5be0ea25..a5171d0bb50f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgInit.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgInit.java @@ -1,21 +1,24 @@ package org.zmlx.hg4idea.action; +import com.intellij.ide.impl.NewProjectUtil; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileChooser.FileChooser; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsDirectoryMapping; import com.intellij.openapi.vfs.VirtualFile; +import org.zmlx.hg4idea.HgUtil; import org.zmlx.hg4idea.HgVcs; import org.zmlx.hg4idea.HgVcsMessages; import org.zmlx.hg4idea.command.HgInitCommand; +import org.zmlx.hg4idea.ui.HgInitAlreadyUnderHgDialog; +import org.zmlx.hg4idea.ui.HgInitDialog; import java.util.ArrayList; import java.util.List; @@ -27,49 +30,58 @@ import java.util.List; public class HgInit extends DumbAwareAction { private static final Logger LOG = Logger.getInstance(HgInit.class.getName()); + private Project myProject; public HgInit() { } @Override public void actionPerformed(AnActionEvent e) { - final Project project = e.getData(PlatformDataKeys.PROJECT); - if (project == null) { + myProject = e.getData(PlatformDataKeys.PROJECT); + if (myProject == null) { LOG.warn("[actionPerformed] project is null"); return; } - // 1. provide window to select the root directory (possibly with an option to select project directory - // TODO: dialog: probably the user wants to put the whole project under git, so the root dir of the project is git repo root. No need to select the folder in that case. - final FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor(); - fcd.setTitle(HgVcsMessages.message("hg4idea.init.destination.directory.title")); - fcd.setDescription(HgVcsMessages.message("hg4idea.init.destination.directory.description")); - fcd.setHideIgnored(false); - final VirtualFile baseDir = project.getBaseDir(); - final VirtualFile[] files = FileChooser.chooseFiles(project, fcd, baseDir); - if (files.length == 0) { + // provide window to select the root directory + final HgInitDialog hgInitDialog = new HgInitDialog(myProject); + hgInitDialog.show(); + if (!hgInitDialog.isOK()) { return; } - final VirtualFile root = files[0]; - - // 2. check if it is not yet under mercurial - final HgVcs hgVcs = HgVcs.getInstance(project); - if (hgVcs.isVersionedDirectory(root)) { - Messages.showErrorDialog(project, HgVcsMessages.message("hg4idea.init.error.already.under.hg", root.getPresentableUrl()), - HgVcsMessages.message("hg4idea.init.error.title")); + final VirtualFile selectedRoot = hgInitDialog.getSelectedFolder(); + if (selectedRoot == null) { return; } + // check if it the project is not yet under mercurial and provide some options in that case + final VirtualFile vcsRoot = HgUtil.getNearestHgRoot(selectedRoot); + VirtualFile mapRoot = selectedRoot; + if (vcsRoot != null) { + final HgInitAlreadyUnderHgDialog dialog = new HgInitAlreadyUnderHgDialog(myProject, + selectedRoot.getPresentableUrl(), vcsRoot.getPresentableUrl()); + dialog.show(); + if (!dialog.isOK()) { + return; + } - // 3. Execute hg init - (new HgInitCommand(project)).execute(root); - //TODO: handle errors here + if (dialog.getAnswer() == HgInitAlreadyUnderHgDialog.Answer.CREATE_PROJECT_AT_PARENT) { + NewProjectUtil.createNewProject(myProject, vcsRoot.getPath()); + return; + } else if (dialog.getAnswer() == HgInitAlreadyUnderHgDialog.Answer.USE_PARENT_REPO_BUT_THIS_PROJECT) { + mapRoot = vcsRoot; + } else if (dialog.getAnswer() == HgInitAlreadyUnderHgDialog.Answer.CREATE_REPO_HERE) { + createRepository(selectedRoot); + } + } else { // no parent repository => creating the repository here. + createRepository(selectedRoot); + } - // 4. update vcs directory mappings - root.refresh(false, false); - final String path = root.equals(baseDir) ? "" : root.getPath(); - ProjectLevelVcsManager vcs = ProjectLevelVcsManager.getInstance(project); - final List vcsDirectoryMappings = new ArrayList(vcs.getDirectoryMappings()); + // update vcs directory mappings + mapRoot.refresh(false, false); + final String path = mapRoot.equals(myProject.getBaseDir()) ? "" : mapRoot.getPath(); + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + final List vcsDirectoryMappings = new ArrayList(vcsManager.getDirectoryMappings()); VcsDirectoryMapping mapping = new VcsDirectoryMapping(path, HgVcs.VCS_NAME); for (int i = 0; i < vcsDirectoryMappings.size(); i++) { final VcsDirectoryMapping m = vcsDirectoryMappings.get(i); @@ -88,8 +100,8 @@ public class HgInit extends DumbAwareAction { if (mapping != null) { vcsDirectoryMappings.add(mapping); } - vcs.setDirectoryMappings(vcsDirectoryMappings); - vcs.updateActiveVcss(); + vcsManager.setDirectoryMappings(vcsDirectoryMappings); + vcsManager.updateActiveVcss(); } @Override @@ -99,5 +111,13 @@ public class HgInit extends DumbAwareAction { presentation.setEnabled(project != null); presentation.setVisible(project != null); } + + private void createRepository(VirtualFile selectedRoot) { + (new HgInitCommand(myProject)).execute(selectedRoot); + Notifications.Bus.notify(new Notification(HgVcs.NOTIFICATION_GROUP_ID, + HgVcsMessages.message("hg4idea.init.created.notification.title"), + HgVcsMessages.message("hg4idea.init.created.notification.description", selectedRoot.getPresentableUrl()), + NotificationType.INFORMATION), myProject); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java index 11af41ca2752..4287d3104308 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java @@ -17,6 +17,7 @@ package org.zmlx.hg4idea.provider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.CheckoutProvider; import com.intellij.openapi.vfs.LocalFileSystem; @@ -24,6 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgUtil; +import org.zmlx.hg4idea.HgVcsMessages; import org.zmlx.hg4idea.command.HgCloneCommand; import org.zmlx.hg4idea.command.HgCommandResult; import org.zmlx.hg4idea.ui.HgCloneDialog; @@ -35,6 +37,8 @@ import java.io.File; */ public class HgCheckoutProvider implements CheckoutProvider { + private HgCommandResult myCloneResult; + /** * {@inheritDoc} */ @@ -45,7 +49,7 @@ public class HgCheckoutProvider implements CheckoutProvider { } }); - HgCloneDialog dialog = new HgCloneDialog(project); + final HgCloneDialog dialog = new HgCloneDialog(project); dialog.show(); if (!dialog.isOK()) { return; @@ -54,17 +58,21 @@ public class HgCheckoutProvider implements CheckoutProvider { if (destinationParent == null) { return; } - String targetDir = destinationParent.getPath() + File.separator + dialog.getDirectoryName(); + final String targetDir = destinationParent.getPath() + File.separator + dialog.getDirectoryName(); - final String sourceRepositoryURL = dialog.getSourceRepositoryURL(); - HgCloneCommand clone = new HgCloneCommand(project); - clone.setRepositoryURL(sourceRepositoryURL); - clone.setDirectory(targetDir); - HgCommandResult result = clone.execute(); + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + public void run() { + HgCloneCommand clone = new HgCloneCommand(project); + clone.setRepositoryURL(dialog.getSourceRepositoryURL()); + clone.setDirectory(targetDir); + myCloneResult = clone.execute(); - HgUtil.markDirectoryDirty(project,destinationParent); + } + }, HgVcsMessages.message("hg4idea.clone.progress", dialog.getSourceRepositoryURL()), false, project); - if (result.getExitValue() == 0) { + HgUtil.markDirectoryDirty(project, destinationParent); + + if (myCloneResult.getExitValue() == 0) { if (listener != null) { listener.directoryCheckedOut(new File(dialog.getParentDirectory(), dialog.getDirectoryName())); } @@ -72,6 +80,7 @@ public class HgCheckoutProvider implements CheckoutProvider { if (listener != null) { listener.checkoutCompleted(); } + } /** diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java index 32d1ec1582fe..e420d5ca923e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java @@ -16,6 +16,7 @@ package org.zmlx.hg4idea.ui; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; import com.intellij.openapi.vfs.VirtualFile; @@ -180,20 +181,28 @@ public class HgCloneDialog extends DialogWrapper { updateCloneButton(); } }); + testButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { testURL = repositoryURL.getText(); - boolean succeeded = testRepository(project, testURL); - if (succeeded) { + final boolean finished = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + public void run() { + testResult = testRepository(project, testURL); + } + }, HgVcsMessages.message("hg4idea.clone.test.progress", testURL), true, project, clonePanel); + + if (!finished) { + return; + } + + if (testResult) { Messages.showInfoMessage(testButton, HgVcsMessages.message("hg4idea.clone.test.success.message", testURL), - HgVcsMessages.message("hg4idea.clone.test.success")); - testResult = Boolean.TRUE; - } else { - testResult = Boolean.FALSE; + HgVcsMessages.message("hg4idea.clone.test.success")); } updateCloneButton(); } }); + setOKActionEnabled(false); } @@ -336,7 +345,7 @@ public class HgCloneDialog extends DialogWrapper { return "reference.VersionControl.Hg.CloneRepository"; } - private boolean testRepository(Project project, final String repositoryUrl) { + private static boolean testRepository(Project project, final String repositoryUrl) { HgIdentifyCommand identifyCommand = new HgIdentifyCommand(project); identifyCommand.setSource(repositoryUrl); HgCommandResult result = identifyCommand.execute(); @@ -344,109 +353,4 @@ public class HgCloneDialog extends DialogWrapper { return result.getExitValue() == 0; } - { -// GUI initializer generated by IntelliJ IDEA GUI Designer -// >>> IMPORTANT!! <<< -// DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - clonePanel = new JPanel(); - clonePanel.setLayout(new GridLayoutManager(4, 4, new Insets(0, 0, 0, 0), -1, -1)); - final JLabel label1 = new JLabel(); - this.$$$loadLabelText$$$(label1, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.repository.url")); - clonePanel.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - clonePanel.add(spacer1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - final Spacer spacer2 = new Spacer(); - clonePanel.add(spacer2, new GridConstraints(3, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - repositoryURL = new JTextField(); - clonePanel.add(repositoryURL, new GridConstraints(0, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); - final JLabel label2 = new JLabel(); - this.$$$loadLabelText$$$(label2, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.parent.directory")); - clonePanel.add(label2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - parentDirectory = new TextFieldWithBrowseButton(); - clonePanel.add(parentDirectory, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final JLabel label3 = new JLabel(); - this.$$$loadLabelText$$$(label3, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.directory.name")); - clonePanel.add(label3, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - testButton = new JButton(); - this.$$$loadButtonText$$$(testButton, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.button.test")); - clonePanel.add(testButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - directoryName = new JTextField(); - clonePanel.add(directoryName, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); - final Spacer spacer3 = new Spacer(); - clonePanel.add(spacer3, new GridConstraints(2, 2, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - label1.setLabelFor(repositoryURL); - label3.setLabelFor(directoryName); - } - - /** - * @noinspection ALL - */ - private void $$$loadLabelText$$$(JLabel component, String text) { - StringBuffer result = new StringBuffer(); - boolean haveMnemonic = false; - char mnemonic = '\0'; - int mnemonicIndex = -1; - for (int i = 0; i < text.length(); i++) { - if (text.charAt(i) == '&') { - i++; - if (i == text.length()) break; - if (!haveMnemonic && text.charAt(i) != '&') { - haveMnemonic = true; - mnemonic = text.charAt(i); - mnemonicIndex = result.length(); - } - } - result.append(text.charAt(i)); - } - component.setText(result.toString()); - if (haveMnemonic) { - component.setDisplayedMnemonic(mnemonic); - component.setDisplayedMnemonicIndex(mnemonicIndex); - } - } - - /** - * @noinspection ALL - */ - private void $$$loadButtonText$$$(AbstractButton component, String text) { - StringBuffer result = new StringBuffer(); - boolean haveMnemonic = false; - char mnemonic = '\0'; - int mnemonicIndex = -1; - for (int i = 0; i < text.length(); i++) { - if (text.charAt(i) == '&') { - i++; - if (i == text.length()) break; - if (!haveMnemonic && text.charAt(i) != '&') { - haveMnemonic = true; - mnemonic = text.charAt(i); - mnemonicIndex = result.length(); - } - } - result.append(text.charAt(i)); - } - component.setText(result.toString()); - if (haveMnemonic) { - component.setMnemonic(mnemonic); - component.setDisplayedMnemonicIndex(mnemonicIndex); - } - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return clonePanel; - } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.form new file mode 100644 index 000000000000..ba638f81ca58 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.form @@ -0,0 +1,58 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.java new file mode 100644 index 000000000000..ecb0fc2e2b2a --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitAlreadyUnderHgDialog.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zmlx.hg4idea.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TitlePanel; +import org.zmlx.hg4idea.HgVcsMessages; + +import javax.swing.*; + +/** + * The dialog which appears, when user wants to create a Mercurial repository in the folder, + * which is already under Mercurial. + * Provides several options to choose. + */ +public class HgInitAlreadyUnderHgDialog extends DialogWrapper { + private JPanel contentPane; + private JRadioButton myCreateNewRepositoryHereRadioButton; + private JRadioButton myUseParentRepoButThisProjectButton; + private JRadioButton myUseParentRepoAndCreateProjectButton; + private TitlePanel myTitlePanel; + private String myParentRoot; + private String mySelectedRoot; + + public enum Answer { + CREATE_PROJECT_AT_PARENT, + USE_PARENT_REPO_BUT_THIS_PROJECT, + CREATE_REPO_HERE + } + + public HgInitAlreadyUnderHgDialog(Project project, String selectedRoot, String parentRoot) { + super(project, false); + mySelectedRoot = selectedRoot; + myParentRoot = parentRoot; + setTitle(HgVcsMessages.message("hg4idea.init.already.under.hg.dialog.title")); + init(); + } + + public Answer getAnswer() { + if (myCreateNewRepositoryHereRadioButton.isSelected()) { + return Answer.CREATE_REPO_HERE; + } else if (myUseParentRepoAndCreateProjectButton.isSelected()) { + return Answer.CREATE_PROJECT_AT_PARENT; + } else { + return Answer.USE_PARENT_REPO_BUT_THIS_PROJECT; + } + } + + @Override + protected void init() { + super.init(); + final ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(myCreateNewRepositoryHereRadioButton); + buttonGroup.add(myUseParentRepoAndCreateProjectButton); + buttonGroup.add(myUseParentRepoButThisProjectButton); + } + + @Override + protected JComponent createCenterPanel() { + return contentPane; + } + + private void createUIComponents() { + myTitlePanel = new TitlePanel(HgVcsMessages.message("hg4idea.init.already.under.hg.title"), + HgVcsMessages.message("hg4idea.init.already.under.hg.description", mySelectedRoot, myParentRoot)); + } + +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.form new file mode 100644 index 000000000000..712cb49e42fe --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.form @@ -0,0 +1,59 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java new file mode 100644 index 000000000000..1c7d515dff94 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgInitDialog.java @@ -0,0 +1,168 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zmlx.hg4idea.ui; + +import com.intellij.openapi.fileChooser.FileChooser; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcsUtil.VcsUtil; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgUtil; +import org.zmlx.hg4idea.HgVcsMessages; + +import javax.swing.*; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * The HgInitDialog appears when user wants to create new Mercurial repository, in response to the + * {@link org.zmlx.hg4idea.action.HgInit} action. + * It provides two options - create repository for the whole project or select a directory for the repository. + * Also if the project directory already is a mercurial root, then no options are provided. + * Instead a file chooser appears to select directory for the repository. + * + * @see org.zmlx.hg4idea.action.HgInit + * @author Kirill Likhodedov + */ +public class HgInitDialog extends DialogWrapper { + private JPanel contentPane; + private JRadioButton myCreateRepositoryForTheRadioButton; + private JRadioButton mySelectWhereToCreateRadioButton; + private TextFieldWithBrowseButton myTextFieldBrowser; + private final Project myProject; + private VirtualFile mySelectedDir; + private FileChooserDescriptor myFileDescriptor; + private boolean myIsProjectBaseDirHgRoot; // basing on this field, show options or invoke file chooser at once + + public HgInitDialog(Project project) { + super(project); + myProject = project; + myIsProjectBaseDirHgRoot = HgUtil.isHgRoot(myProject.getBaseDir()); + init(); + } + + @Override + protected void init() { + super.init(); + setTitle(HgVcsMessages.message("hg4idea.init.dialog.title")); + mySelectedDir = myProject.getBaseDir(); + + mySelectWhereToCreateRadioButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myTextFieldBrowser.setEnabled(true); + updateEverything(); + } + }); + myCreateRepositoryForTheRadioButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myTextFieldBrowser.setEnabled(false); + updateEverything(); + } + }); + myTextFieldBrowser.getTextField().addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { + updateEverything(); + } + }); + + myFileDescriptor = new FileChooserDescriptor(false, true, false, false, false, false) { + public void validateSelectedFiles(VirtualFile[] files) throws Exception { + if (HgUtil.isHgRoot(files[0])) { + throw new ConfigurationException(HgVcsMessages.message("hg4idea.init.this.is.hg.root", files[0].getPresentableUrl())); + } + updateEverything(); + } + }; + myFileDescriptor.setHideIgnored(false); + myTextFieldBrowser.addBrowseFolderListener(HgVcsMessages.message("hg4idea.init.destination.directory.title"), + HgVcsMessages.message("hg4idea.init.destination.directory.description"), + myProject, myFileDescriptor); + } + + /** + * Show the dialog OR show a FileChooser to select target directory. + */ + @Override + public void show() { + if (myIsProjectBaseDirHgRoot) { + final VirtualFile[] files = FileChooser.chooseFiles(myProject, myFileDescriptor, myProject.getBaseDir()); + mySelectedDir = (files.length == 0 ? null : files[0]); + } else { + super.show(); + } + } + + @Override + public boolean isOK() { + if (myIsProjectBaseDirHgRoot) { + return mySelectedDir != null; + } + return super.isOK(); + } + + @Nullable + public VirtualFile getSelectedFolder() { + return mySelectedDir; + } + + @Override + protected JComponent createCenterPanel() { + return contentPane; + } + + /** + * Based on the selected option and entered path to the target directory, + * enable/disable the 'OK' button, show error text and update mySelectedDir. + */ + private void updateEverything() { + if (myCreateRepositoryForTheRadioButton.isSelected()) { + enableOKAction(); + mySelectedDir = myProject.getBaseDir(); + } else { + final VirtualFile vf = VcsUtil.getVirtualFile(myTextFieldBrowser.getText()); + if (vf == null) { + disableOKAction(); + mySelectedDir = null; + return; + } + vf.refresh(false, false); + if (vf.exists() && vf.isValid() && vf.isDirectory()) { + enableOKAction(); + mySelectedDir = vf; + } else { + disableOKAction(); + mySelectedDir = null; + } + } + } + + private void enableOKAction() { + setErrorText(null); + setOKActionEnabled(true); + } + + private void disableOKAction() { + setErrorText(HgVcsMessages.message("hg4idea.init.dialog.incorrect.path")); + setOKActionEnabled(false); + } + +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java index dd76ce5f0aa8..c3c198d82729 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java @@ -95,43 +95,4 @@ public class HgPullDialog extends DialogWrapper { setOKActionEnabled(StringUtils.isNotBlank(sourceTxt.getText())); } - { -// GUI initializer generated by IntelliJ IDEA GUI Designer -// >>> IMPORTANT!! <<< -// DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - mainPanel = new JPanel(); - mainPanel.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1)); - hgRepositorySelector = new HgRepositorySelectorComponent(); - mainPanel.add(hgRepositorySelector.$$$getRootComponent$$$(), new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - mainPanel.add(spacer1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - final JPanel panel1 = new JPanel(); - panel1.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1)); - mainPanel.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - final JLabel label1 = new JLabel(); - label1.setText("Pull From:"); - panel1.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer2 = new Spacer(); - panel1.add(spacer2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - sourceTxt = new JTextField(); - panel1.add(sourceTxt, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return mainPanel; - } }