IDEA-64622 Git clone remembers visited urls.
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Mon, 4 Apr 2011 09:03:20 +0000 (13:03 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Mon, 4 Apr 2011 09:14:42 +0000 (13:14 +0400)
GitRememberedInputs - PersistentStateComponent to remember user inputs across Git.
GitClone to remember visited urls and offer dropdown list.
Parent dir is also remembered.

plugins/git4idea/src/META-INF/plugin.xml
plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
plugins/git4idea/src/git4idea/checkout/GitCloneDialog.form
plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java [new file with mode: 0644]

index 7848a0ae352cb85667d8753baa65d293418d0020..e5083e029bcb53b607060291de42eaf8e5463d3d 100644 (file)
     <applicationService
         serviceInterface="git4idea.config.SSHConnectionSettings"
         serviceImplementation="git4idea.config.SSHConnectionSettings"/>
+    <applicationService
+        serviceInterface="git4idea.remote.GitRememberedInputs"
+        serviceImplementation="git4idea.remote.GitRememberedInputs"/>
 
     <ComponentRoamingType component="Git.Settings" type="DISABLED"/>
     <fileTypeFactory implementation="git4idea.vfs.GitFileTypeFactory"/>
index 7b012e09af4e86a110a175835abcdd9dcfab5722..2b0e84312a32dda322b48ca107ed3186746e0c8a 100644 (file)
@@ -22,11 +22,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import git4idea.GitVcs;
 import git4idea.actions.BasicAction;
-import git4idea.commands.GitCommand;
-import git4idea.commands.GitLineHandler;
-import git4idea.commands.GitStandardProgressAnalyzer;
-import git4idea.commands.GitTask;
-import git4idea.commands.GitTaskResultHandlerAdapter;
+import git4idea.commands.*;
 import git4idea.config.GitVersion;
 import git4idea.i18n.GitBundle;
 import git4idea.ui.GitUIUtil;
@@ -55,6 +51,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
     if (!dialog.isOK()) {
       return;
     }
+    dialog.rememberSettings();
     final VirtualFile destinationParent = LocalFileSystem.getInstance().findFileByIoFile(new File(dialog.getParentDirectory()));
     if (destinationParent == null) {
       return;
index fdccdd6fa2b1b21dff4edf2448671f3e1686ba7a..fc6cc9b1734c5bf00abaa07052f6ad6f4afb5ae5 100644 (file)
@@ -3,7 +3,7 @@
   <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="5" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="20" y="20" width="567" height="128"/>
+      <xy x="20" y="20" width="567" height="152"/>
     </constraints>
     <properties/>
     <border type="none"/>
@@ -13,7 +13,7 @@
           <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
-          <labelFor value="9bab4"/>
+          <labelFor value="b8c8e"/>
           <text resource-bundle="git4idea/i18n/GitBundle" key="clone.repository.url"/>
         </properties>
       </component>
@@ -27,7 +27,7 @@
           <grid row="4" column="1" row-span="1" col-span="3" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
         </constraints>
       </hspacer>
-      <component id="9bab4" class="javax.swing.JTextField" binding="myRepositoryURL">
+      <component id="b8c8e" class="com.intellij.ui.EditorComboBox" binding="myRepositoryURL" custom-create="true">
         <constraints>
           <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
             <preferred-size width="150" height="-1"/>
index 021a02332e620e4be715c3134d8b35e83c619937..c2c16466549fa0992fcddc14732641553e7d3172 100644 (file)
@@ -17,24 +17,21 @@ package git4idea.checkout;
 
 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.ComponentWithBrowseButton;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.TextComponentAccessor;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.ui.*;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.EditorComboBox;
+import com.intellij.util.ArrayUtil;
 import git4idea.commands.GitCommand;
 import git4idea.commands.GitSimpleHandler;
 import git4idea.commands.GitTask;
 import git4idea.commands.GitTaskResult;
 import git4idea.i18n.GitBundle;
+import git4idea.remote.GitRememberedInputs;
 import git4idea.validators.GitBranchNameValidator;
 import org.jetbrains.annotations.NonNls;
 
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
+import javax.swing.*;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import java.awt.event.ActionEvent;
@@ -65,7 +62,7 @@ public class GitCloneDialog extends DialogWrapper {
   }
 
   private JPanel myRootPanel;
-  private JTextField myRepositoryURL;
+  private EditorComboBox myRepositoryURL;
   private TextFieldWithBrowseButton myParentDirectory;
   private JButton myTestButton; // test repository
   private JTextField myDirectoryName;
@@ -125,49 +122,19 @@ public class GitCloneDialog extends DialogWrapper {
           }
           return super.getInitialFile();
         }
-      });
-    final DocumentListener updateOkButtonListener = new DocumentListener() {
-      // update Ok button state depending on the current state of the fields
-      public void insertUpdate(final DocumentEvent e) {
-        updateOkButton();
-      }
-
-      public void removeUpdate(final DocumentEvent e) {
-        updateOkButton();
-      }
+    });
 
-      public void changedUpdate(final DocumentEvent e) {
-        updateOkButton();
+    final DocumentListener updateOkButtonListener = new DocumentAdapter() {
+      @Override protected void textChanged(DocumentEvent e) {
+        updateButtons();
       }
     };
     myParentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
+    myParentDirectory.setText(GitRememberedInputs.getInstance().getCloneParentDir());
+
     myDirectoryName.getDocument().addDocumentListener(updateOkButtonListener);
     myOriginName.getDocument().addDocumentListener(updateOkButtonListener);
-    myRepositoryURL.getDocument().addDocumentListener(new DocumentListener() {
-      // enable test button only if something is entered in repository URL
-      public void insertUpdate(final DocumentEvent e) {
-        changed();
-      }
-
-      public void removeUpdate(final DocumentEvent e) {
-        changed();
-      }
-
-      public void changedUpdate(final DocumentEvent e) {
-        changed();
-      }
 
-      private void changed() {
-        final String url = myRepositoryURL.getText();
-        myTestButton.setEnabled(url.length() != 0);
-        if (myDefaultDirectoryName.equals(myDirectoryName.getText()) || myDirectoryName.getText().length() == 0) {
-          // modify field if it was unmodified or blank
-          myDefaultDirectoryName = defaultDirectoryName(url);
-          myDirectoryName.setText(myDefaultDirectoryName);
-        }
-        updateOkButton();
-      }
-    });
     myTestButton.addActionListener(new ActionListener() {
       public void actionPerformed(final ActionEvent e) {
         myTestURL = myRepositoryURL.getText();
@@ -184,16 +151,18 @@ public class GitCloneDialog extends DialogWrapper {
         } else {
           myTestResult = Boolean.FALSE;
         }
-        updateOkButton();
+        updateButtons();
       }
     });
+
     setOKActionEnabled(false);
+    myTestButton.setEnabled(false);
   }
 
   /**
    * Check fields and display error in the wrapper if there is a problem
    */
-  private void updateOkButton() {
+  private void updateButtons() {
     if (!checkRepositoryURL()) {
       return;
     }
@@ -300,6 +269,32 @@ public class GitCloneDialog extends DialogWrapper {
     return false;
   }
 
+  private void createUIComponents() {
+    myRepositoryURL = new EditorComboBox("");
+    final GitRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
+    myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
+    myRepositoryURL.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
+      @Override
+      public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
+        // enable test button only if something is entered in repository URL
+        final String url = myRepositoryURL.getText();
+        myTestButton.setEnabled(url.length() != 0);
+        if (myDefaultDirectoryName.equals(myDirectoryName.getText()) || myDirectoryName.getText().length() == 0) {
+          // modify field if it was unmodified or blank
+          myDefaultDirectoryName = defaultDirectoryName(url);
+          myDirectoryName.setText(myDefaultDirectoryName);
+        }
+        updateButtons();
+      }
+    });
+  }
+
+  public void rememberSettings() {
+    final GitRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
+    rememberedInputs.addUrl(getSourceRepositoryURL());
+    rememberedInputs.setCloneParentDir(getParentDirectory());
+  }
+
   /**
    * Get default name for checked out directory
    *
@@ -328,16 +323,10 @@ public class GitCloneDialog extends DialogWrapper {
     return i >= 0 ? nonSystemName.substring(i + 1) : "";
   }
 
-  /**
-   * {@inheritDoc}
-   */
   protected JComponent createCenterPanel() {
     return myRootPanel;
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getDimensionServiceKey() {
     return "GitCloneDialog";
@@ -348,9 +337,6 @@ public class GitCloneDialog extends DialogWrapper {
     return myRepositoryURL;
   }
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
   protected String getHelpId() {
     return "reference.VersionControl.Git.CloneRepository";
diff --git a/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java b/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java
new file mode 100644 (file)
index 0000000..cad02be
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2011 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 git4idea.remote;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Kirill Likhodedov
+ */
+@State(
+  name = "GitRememberedInputs",
+  storages = @Storage(id = "GitRememberedInputs", file = "$APP_CONFIG$/vcs.xml")
+)
+public class GitRememberedInputs implements PersistentStateComponent<GitRememberedInputs.State> {
+
+  private State myState = new State();
+
+  public static GitRememberedInputs getInstance() {
+    return ServiceManager.getService(GitRememberedInputs.class);
+  }
+
+  @Override
+  public State getState() {
+    return myState;
+  }
+
+  @Override
+  public void loadState(State state) {
+    myState = state;
+  }
+
+  public void addUrl(String url) {
+    myState.myVisitedUrls.add(url);
+  }
+
+  public List<String> getVisitedUrls() {
+    return myState.myVisitedUrls;
+  }
+
+  public String getCloneParentDir() {
+    return myState.myCloneParentDir;
+  }
+
+  public void setCloneParentDir(String cloneParentDir) {
+    myState.myCloneParentDir = cloneParentDir;
+  }
+
+  public static class State {
+    public List<String> myVisitedUrls = new ArrayList<String>();
+    public String myCloneParentDir = "";
+  }
+}