diff --git a/platform/util/src/com/intellij/util/ui/FormBuilder.java b/platform/util/src/com/intellij/util/ui/FormBuilder.java
index fe190d15fb0e..5b1088debd19 100644
--- a/platform/util/src/com/intellij/util/ui/FormBuilder.java
+++ b/platform/util/src/com/intellij/util/ui/FormBuilder.java
@@ -19,6 +19,7 @@
*/
package com.intellij.util.ui;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -52,49 +53,46 @@ public class FormBuilder {
return new FormBuilder();
}
- public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component) {
+ public FormBuilder addLabeledComponent(@Nullable JComponent label, @NotNull JComponent component) {
return addLabeledComponent(label, component, myVerticalGap, false);
}
- public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component, final int topInset) {
+ public FormBuilder addLabeledComponent(@Nullable JComponent label, @NotNull JComponent component, final int topInset) {
return addLabeledComponent(label, component, topInset, false);
}
- public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component, boolean labelOnTop) {
+ public FormBuilder addLabeledComponent(@Nullable JComponent label, @NotNull JComponent component, boolean labelOnTop) {
return addLabeledComponent(label, component, myVerticalGap, labelOnTop);
}
- public FormBuilder addLabeledComponent(String labelText, JComponent component) {
+ public FormBuilder addLabeledComponent(@NotNull String labelText, @NotNull JComponent component) {
return addLabeledComponent(labelText, component, myVerticalGap, false);
}
- public FormBuilder addLabeledComponent(String labelText, JComponent component, final int topInset) {
+ public FormBuilder addLabeledComponent(@NotNull String labelText, @NotNull JComponent component, final int topInset) {
return addLabeledComponent(labelText, component, topInset, false);
}
- public FormBuilder addLabeledComponent(String labelText, JComponent component, boolean labelOnTop) {
+ public FormBuilder addLabeledComponent(@NotNull String labelText, @NotNull JComponent component, boolean labelOnTop) {
return addLabeledComponent(labelText, component, myVerticalGap, labelOnTop);
}
- public FormBuilder addLabeledComponent(String labelText, JComponent component, final int topInset, boolean labelOnTop) {
- JLabel label = null;
- if (labelText != null) {
- label = new JLabel(UIUtil.removeMnemonic(labelText));
- final int index = UIUtil.getDisplayMnemonicIndex(labelText);
- if (index != -1) {
- label.setDisplayedMnemonic(labelText.charAt(index + 1));
- }
- label.setLabelFor(component);
+ public FormBuilder addLabeledComponent(@NotNull String labelText, @NotNull JComponent component, final int topInset, boolean labelOnTop) {
+ JLabel label = new JLabel(UIUtil.removeMnemonic(labelText));
+ final int index = UIUtil.getDisplayMnemonicIndex(labelText);
+ if (index != -1) {
+ label.setDisplayedMnemonic(labelText.charAt(index + 1));
}
+ label.setLabelFor(component);
return addLabeledComponent(label, component, topInset, labelOnTop);
}
- public FormBuilder addComponent(JComponent component) {
+ public FormBuilder addComponent(@NotNull JComponent component) {
return addLabeledComponent((JLabel)null, component, myVerticalGap, false);
}
- public FormBuilder addComponent(JComponent component, final int topInset) {
+ public FormBuilder addComponent(@NotNull JComponent component, final int topInset) {
return addLabeledComponent((JLabel)null, component, topInset, false);
}
@@ -111,7 +109,7 @@ public class FormBuilder {
new Box.Filler(new Dimension(0, height), new Dimension(0, height), new Dimension(Short.MAX_VALUE, height)));
}
- public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component, int topInset, boolean labelOnTop) {
+ public FormBuilder addLabeledComponent(@Nullable JComponent label, @NotNull JComponent component, int topInset, boolean labelOnTop) {
GridBagConstraints c = new GridBagConstraints();
topInset = myLineCount > 0 ? topInset : 0;
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index 25236800c7b0..876a33516e50 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.java
@@ -388,9 +388,9 @@ public class UIUtil {
int defSize = getLabelFont().getSize();
switch (size) {
case SMALL:
- return Math.max(defSize - 2f, 11f);
+ return Math.max(defSize - 2f, 10f);
case MINI:
- return Math.max(defSize - 4f, 9f);
+ return Math.max(defSize - 4f, 8f);
default:
return defSize;
}
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
index 9acd06059d54..074ebcfa1acd 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
@@ -146,11 +146,13 @@
-
+
+
+
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
index bc4d8dc39ff4..94e67421b8f0 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
@@ -62,7 +62,7 @@ public class BaseRepositoryEditor extends TaskReposito
private JPanel myCustomPanel;
private JBCheckBox myAddCommitMessage;
- private JLabel myComment;
+ private JBLabel myComment;
private JPanel myEditorPanel;
private boolean myApplying;
diff --git a/plugins/tasks/tasks-core/src/META-INF/plugin.xml b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
index 4e74c57fc7e8..84346733e975 100644
--- a/plugins/tasks/tasks-core/src/META-INF/plugin.xml
+++ b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
@@ -116,6 +116,7 @@
+
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepository.java
new file mode 100644
index 000000000000..bc2b0115b8fd
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepository.java
@@ -0,0 +1,252 @@
+package com.intellij.tasks.connector;
+
+import com.intellij.openapi.util.Comparing;
+import com.intellij.tasks.Comment;
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskRepositoryType;
+import com.intellij.tasks.TaskType;
+import com.intellij.tasks.impl.BaseRepository;
+import com.intellij.tasks.impl.BaseRepositoryImpl;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import icons.TasksIcons;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: Evgeny.Zakrevsky
+ * Date: 10/4/12
+ */
+@Tag("Web")
+public class WebRepository extends BaseRepositoryImpl {
+ private String myTasksListURL;
+ private String myTaskPattern;
+ private String myLoginURL;
+
+ final static String SERVER_URL_PLACEHOLDER = "{serverUrl}";
+ final static String USERNAME_PLACEHOLDER = "{username}";
+ final static String PASSWORD_PLACEHOLDER = "{password}";
+ final static String ID_PLACEHOLDER = "{id}";
+ final static String SUMMARY_PLACEHOLDER = "{summary}";
+ final static String DESCRIPTION_PLACEHOLDER = "{description}";
+ final static String PAGE_PLACEHOLDER = "{page}";
+
+ //final Map myPlaceholder2Value = new HashMap();
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public WebRepository() {
+ }
+
+ public WebRepository(final TaskRepositoryType type) {
+ super(type);
+ }
+
+ public WebRepository(final WebRepository other) {
+ super(other);
+ myTasksListURL = other.getTasksListURL();
+ myTaskPattern = other.getTaskPattern();
+ myLoginURL = other.getLoginURL();
+ }
+
+ @Override
+ public Task[] getIssues(@Nullable final String query, final int max, final long since) throws Exception {
+ final HttpClient httpClient = getHttpClient();
+ login(httpClient);
+
+ final GetMethod getMethod = new GetMethod(getFullTasksUrl());
+ httpClient.executeMethod(getMethod);
+ final String response = getMethod.getResponseBodyAsString(Integer.MAX_VALUE);
+
+ final String taskPatternWithoutPlaceholders = myTaskPattern.replaceAll("\\{.+?\\}", "");
+ Matcher matcher = Pattern
+ .compile(taskPatternWithoutPlaceholders,
+ Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.UNICODE_CASE | Pattern.CANON_EQ)
+ .matcher(response);
+
+ final List placeholders = getPlaceholders(myTaskPattern);
+ if (matcher.groupCount() != 2 || !placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
+ throw new Exception("Incorrect Task Pattern");
+ }
+
+ List tasks = new ArrayList();
+ while (matcher.find()) {
+ final String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1);
+ final String description = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1);
+ tasks.add(new Task() {
+ @NotNull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @NotNull
+ @Override
+ public String getSummary() {
+ return description;
+ }
+
+ @Nullable
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Comment[] getComments() {
+ return new Comment[0];
+ }
+
+ @Nullable
+ @Override
+ public Icon getIcon() {
+ return TasksIcons.Other;
+ }
+
+ @NotNull
+ @Override
+ public TaskType getType() {
+ return TaskType.OTHER;
+ }
+
+ @Nullable
+ @Override
+ public Date getUpdated() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Date getCreated() {
+ return null;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public boolean isIssue() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public String getIssueUrl() {
+ return null;
+ }
+ });
+ }
+
+
+ return tasks.toArray(new Task[tasks.size()]);
+ }
+
+ private void login(final HttpClient httpClient) throws IOException {
+ final GetMethod method = new GetMethod(getFullLoginUrl());
+ httpClient.executeMethod(method);
+ }
+
+ private static List getPlaceholders(String value) {
+ if (value == null) {
+ return ContainerUtil.emptyList();
+ }
+
+ List vars = new ArrayList();
+ Matcher m = Pattern.compile("\\{(.+?)\\}").matcher(value);
+ while (m.find()) {
+ vars.add(m.group(0));
+ }
+ return vars;
+ }
+
+ private String getFullTasksUrl() {
+ return getTasksListURL()
+ .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl());
+ }
+
+ private String getFullLoginUrl() {
+ return getLoginURL()
+ .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl())
+ .replaceAll(placeholder2regexp(USERNAME_PLACEHOLDER), getUsername())
+ .replaceAll(placeholder2regexp(PASSWORD_PLACEHOLDER), getPassword());
+ }
+
+ private static String placeholder2regexp(String placeholder) {
+ return placeholder.replaceAll("\\{", "\\\\{");
+ }
+
+ @Nullable
+ @Override
+ public Task findTask(final String id) throws Exception {
+ return null;
+ }
+
+ @Override
+ public BaseRepository clone() {
+ return new WebRepository(this);
+ }
+
+ public String getTasksListURL() {
+ return myTasksListURL;
+ }
+
+ public void setTasksListURL(final String tasksListURL) {
+ myTasksListURL = tasksListURL;
+ }
+
+ public String getTaskPattern() {
+ return myTaskPattern;
+ }
+
+ public void setTaskPattern(final String taskPattern) {
+ myTaskPattern = taskPattern;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WebRepository)) return false;
+ if (!super.equals(o)) return false;
+ WebRepository that = (WebRepository)o;
+ if (!Comparing.equal(getTasksListURL(), that.getTasksListURL())) return false;
+ if (!Comparing.equal(getTaskPattern(), that.getTaskPattern())) return false;
+ if (!Comparing.equal(getLoginURL(), that.getLoginURL())) return false;
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public CancellableConnection createCancellableConnection() {
+ return new CancellableConnection() {
+ @Override
+ protected void doTest() throws Exception {
+ final Task[] issues = getIssues("", 0, 0);
+ if (issues.length == 0) throw new Exception("Tasks not found. Probably, you don't login.");
+ }
+
+ @Override
+ public void cancel() {
+ }
+ };
+ }
+
+ public String getLoginURL() {
+ return myLoginURL;
+ }
+
+ public void setLoginURL(final String loginURL) {
+ myLoginURL = loginURL;
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryEditor.java
new file mode 100644
index 000000000000..3dabbcc8e26f
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryEditor.java
@@ -0,0 +1,77 @@
+package com.intellij.tasks.connector;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.tasks.config.BaseRepositoryEditor;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.Consumer;
+import com.intellij.util.ui.FormBuilder;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * User: Evgeny.Zakrevsky
+ * Date: 10/4/12
+ */
+public class WebRepositoryEditor extends BaseRepositoryEditor {
+ private JBLabel myTasksListURLLabel;
+ private JBLabel myTaskPatternLabel;
+ private JTextField myTasksListURLText;
+ private JTextField myTaskPatternText;
+ private JBLabel myLoginURLLabel;
+ private JTextField myLoginURLText;
+
+ public WebRepositoryEditor(final Project project, final WebRepository repository, final Consumer changeListener) {
+ super(project, repository, changeListener);
+ myUrlLabel.setText("{serverUrl}:");
+ myUsernameLabel.setText("{username}:");
+ myPasswordLabel.setText("{password}:");
+
+ //setAnchor(myUsernameLabel);
+ }
+
+ @Override
+ public void apply() {
+ myRepository.setTasksListURL(myTasksListURLText.getText());
+ myRepository.setTaskPattern(myTaskPatternText.getText());
+ myRepository.setLoginURL(myLoginURLText.getText());
+ super.apply();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCustomPanel() {
+ myTasksListURLLabel = new JBLabel("Tasks List URL:", SwingConstants.RIGHT);
+ myTasksListURLText = new JTextField(myRepository.getTasksListURL());
+ installListener(myTasksListURLText);
+ myTaskPatternLabel = new JBLabel("Task Pattern:", SwingConstants.RIGHT);
+ myTaskPatternText = new JTextField(myRepository.getTaskPattern());
+ installListener(myTaskPatternText);
+ myLoginURLLabel = new JBLabel("Login URL:", SwingConstants.RIGHT);
+ myLoginURLText = new JTextField(myRepository.getLoginURL());
+ installListener(myLoginURLText);
+ return FormBuilder.createFormBuilder().setAlignLabelOnRight(true)
+ .addVerticalGap(8)
+ .addLabeledComponent(myTasksListURLLabel, myTasksListURLText)
+ .addLabeledComponent(new JLabel(), new JBLabel("Available placeholders: " + WebRepository.SERVER_URL_PLACEHOLDER, UIUtil.ComponentStyle.SMALL,
+ UIUtil.FontColor.BRIGHTER), 1)
+ .addLabeledComponent(myTaskPatternLabel, myTaskPatternText, 8)
+ .addLabeledComponent(new JLabel(), new JBLabel("Task pattern should be a regexp with two matching group: ({id}.+?) and ({summary}.+?)",
+ UIUtil.ComponentStyle.SMALL, UIUtil.FontColor.BRIGHTER), 1)
+ .addLabeledComponent(myLoginURLLabel, myLoginURLText, 8)
+ .addLabeledComponent(new JLabel(), new JBLabel("Available placeholders: " + WebRepository.SERVER_URL_PLACEHOLDER + ", " +
+ WebRepository.USERNAME_PLACEHOLDER + ", " + WebRepository.PASSWORD_PLACEHOLDER, UIUtil.ComponentStyle.SMALL,
+ UIUtil.FontColor.BRIGHTER), 1)
+ .addVerticalGap(8)
+ .getPanel();
+ }
+
+ @Override
+ public void setAnchor(@Nullable final JComponent anchor) {
+ super.setAnchor(anchor);
+ myTasksListURLLabel.setAnchor(anchor);
+ myTaskPatternLabel.setAnchor(anchor);
+ myLoginURLLabel.setAnchor(anchor);
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryType.java
new file mode 100644
index 000000000000..21251bee3f02
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/connector/WebRepositoryType.java
@@ -0,0 +1,47 @@
+package com.intellij.tasks.connector;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.project.Project;
+import com.intellij.tasks.TaskRepository;
+import com.intellij.tasks.config.TaskRepositoryEditor;
+import com.intellij.tasks.impl.BaseRepositoryType;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * User: Evgeny.Zakrevsky
+ * Date: 10/4/12
+ */
+public class WebRepositoryType extends BaseRepositoryType {
+ @NotNull
+ @Override
+ public String getName() {
+ return "Web Repository";
+ }
+
+ @Override
+ public Icon getIcon() {
+ return AllIcons.General.Web;
+ }
+
+ @NotNull
+ @Override
+ public TaskRepository createRepository() {
+ return new WebRepository(this);
+ }
+
+ @Override
+ public Class getRepositoryClass() {
+ return WebRepository.class;
+ }
+
+ @NotNull
+ @Override
+ public TaskRepositoryEditor createEditor(final WebRepository repository,
+ final Project project,
+ final Consumer changeListener) {
+ return new WebRepositoryEditor(project, repository, changeListener);
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/icons/TasksIcons.java b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
index 3233faff2144..319c687910dc 100644
--- a/plugins/tasks/tasks-core/src/icons/TasksIcons.java
+++ b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
@@ -16,12 +16,19 @@ public class TasksIcons {
public static final Icon Bug = load("/icons/bug.png"); // 16x16
public static final Icon Exception = load("/icons/exception.png"); // 16x16
public static final Icon Feature = load("/icons/feature.png"); // 16x16
+ public static final Icon Other = load("/icons/other.png"); // 16x16
+ public static final Icon Unknown = load("/icons/unknown.png"); // 16x16
+ public static final Icon SavedContext = load("/icons/savedContext.png"); // 16x16
+
public static final Icon Fogbugz = load("/icons/fogbugz.png"); // 16x16
public static final Icon Github = load("/icons/github.png"); // 16x16
public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16
public static final Icon Mantis = load("/icons/mantis.png"); // 16x16
- public static final Icon Other = load("/icons/other.png"); // 16x16
-
+ public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16
+ public static final Icon Redmine = load("/icons/redmine.png"); // 16x16
+ public static final Icon Trac = load("/icons/trac.png"); // 16x16
+ public static final Icon Youtrack = load("/icons/youtrack.png"); // 16x16
+
public static class Pivotal {
public static final Icon Bug = load("/icons/pivotal/bug.png"); // 14x14
public static final Icon Chore = load("/icons/pivotal/chore.png"); // 14x14
@@ -29,10 +36,4 @@ public class TasksIcons {
public static final Icon Release = load("/icons/pivotal/release.png"); // 14x14
}
- public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16
- public static final Icon Redmine = load("/icons/redmine.png"); // 16x16
- public static final Icon SavedContext = load("/icons/savedContext.png"); // 16x16
- public static final Icon Trac = load("/icons/trac.png"); // 16x16
- public static final Icon Unknown = load("/icons/unknown.png"); // 16x16
- public static final Icon Youtrack = load("/icons/youtrack.png"); // 16x16
}