diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/MoreCommitsLink.java b/platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java similarity index 86% rename from platform/dvcs-impl/src/com/intellij/dvcs/push/MoreCommitsLink.java rename to platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java index e7fdedccc849..71ffa32d93e2 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/MoreCommitsLink.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java @@ -15,8 +15,6 @@ */ package com.intellij.dvcs.push; -public class MoreCommitsLink extends VcsLinkedText { - MoreCommitsLink() { - super("", "..."); - } +public interface CommitLoader { + void reloadCommits(); } diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java index f3ea7adf5634..de2c640d12b1 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java @@ -16,13 +16,28 @@ package com.intellij.dvcs.push; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class VcsError { + @NotNull String myErrorText; + @Nullable private final VcsErrorHandler myErrorHandleListener; -public class VcsError extends VcsLinkedText { public VcsError(@NotNull String text) { - super(text, ""); + this(text, null); } - public VcsError(@NotNull String text, @NotNull String link) { - super(text, link); + public VcsError(@NotNull String text, @Nullable VcsErrorHandler listener) { + myErrorText = text; + myErrorHandleListener = listener; + } + + public String getText() { + return myErrorText; + } + + public void handleError(@NotNull CommitLoader loader) { + if (myErrorHandleListener != null) { + myErrorHandleListener.handleError(loader); + } } } diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java new file mode 100644 index 000000000000..c27e4c7e99d9 --- /dev/null +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2014 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 com.intellij.dvcs.push; + +import org.jetbrains.annotations.NotNull; + +public interface VcsErrorHandler { + void handleError(@NotNull CommitLoader loader); +} diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsLinkedText.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsLinkedText.java deleted file mode 100644 index 99a0d3e77b5d..000000000000 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsLinkedText.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2000-2014 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 com.intellij.dvcs.push; - -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; - -import javax.swing.tree.DefaultMutableTreeNode; -import java.util.List; - -public class VcsLinkedText { - @NotNull String myText; - @NotNull String myHandledLink; - - private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - - public VcsLinkedText(@NotNull String text, @NotNull String link) { - myText = text; - myHandledLink = link; - } - - @NotNull - public String getText() { - return myText; - } - - @NotNull - public String getLinkText() { - return myHandledLink; - } - - public void addClickListener(@NotNull TreeNodeLinkListener listener) { - myListeners.add(listener); - } - - public void fireOnClick(@NotNull DefaultMutableTreeNode relatedNode) { - for (TreeNodeLinkListener listener : myListeners) { - listener.onClick(relatedNode); - } - } -} 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 af1b651b05ee..0adbcafc1076 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -39,7 +39,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.*; @@ -110,7 +109,6 @@ public class PushController implements Disposable { private void loadCommitsFromMap(@NotNull Map items) { for (Map.Entry entry : items.entrySet()) { RepositoryNode node = entry.getKey(); - myPushLog.startLoading(node); loadCommits(entry.getValue(), node, true); } } @@ -156,7 +154,6 @@ public class PushController implements Disposable { public void onTargetChanged(String newValue) { myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue))); myDialog.updateButtons(); - myPushLog.startLoading(repoNode); loadCommits(model, repoNode, false); } @@ -173,6 +170,7 @@ public class PushController implements Disposable { @NotNull final RepositoryNode node, final boolean initial) { node.stopLoading(); + myPushLog.startLoading(node); final ProgressIndicator indicator = node.startLoading(); final PushSupport support = model.getSupport(); final AtomicReference result = new AtomicReference(); @@ -187,10 +185,22 @@ public class PushController implements Disposable { public void onSuccess() { OutgoingResult outgoing = result.get(); if (outgoing.hasErrors()) { + final CommitLoader loader = new CommitLoader() { + @Override + public void reloadCommits() { + loadCommits(model, node, false); + } + }; myPushLog.setChildren(node, ContainerUtil.map(outgoing.getErrors(), new Function() { @Override - public DefaultMutableTreeNode fun(VcsError error) { - return new TextWithLinkNode(error); + public DefaultMutableTreeNode fun(final VcsError error) { + VcsLinkedText errorLinkText = new VcsLinkedText(error.getText(), new VcsLinkListener() { + @Override + public void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode) { + error.handleError(loader); + } + }); + return new TextWithLinkNode(errorLinkText); } }), model.isSelected()); } @@ -288,14 +298,10 @@ public class PushController implements Disposable { List childrenToShown = new ArrayList(); for (int i = 0; i < commits.size(); ++i) { if (i >= commitsNum) { - final MoreCommitsLink moreCommitsLink = new MoreCommitsLink(); - moreCommitsLink.addClickListener(new TreeNodeLinkListener() { + final VcsLinkedText moreCommitsLink = new VcsLinkedText("...", new VcsLinkListener() { @Override - public void onClick(@NotNull DefaultMutableTreeNode source) { - TreeNode parentNode = source.getParent(); - if (parentNode instanceof RepositoryNode) { - addMoreCommits((RepositoryNode)parentNode); - } + public void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode) { + addMoreCommits((RepositoryNode)sourceNode); } }); childrenToShown.add(new TextWithLinkNode(moreCommitsLink)); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java index 9f1bfc229623..685fcb81fd05 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java @@ -16,13 +16,13 @@ package com.intellij.dvcs.push.ui; -import com.intellij.dvcs.push.VcsLinkedText; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.annotations.NotNull; import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; public class TextWithLinkNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode { @@ -32,18 +32,21 @@ public class TextWithLinkNode extends DefaultMutableTreeNode implements CustomRe myLinkedText = linkedText; } - public void fireOnClick(@NotNull TextWithLinkNode relatedNode) { - myLinkedText.fireOnClick(relatedNode); + TreeNode parent = relatedNode.getParent(); + if (parent instanceof RepositoryNode) { + myLinkedText.hyperLinkActivate((RepositoryNode)parent); + } } @Override public void render(@NotNull ColoredTreeCellRenderer renderer) { - renderer.append(myLinkedText.getText(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + renderer.append(myLinkedText.getTextBefore(), SimpleTextAttributes.REGULAR_ATTRIBUTES); String linkedText = myLinkedText.getLinkText(); if (!StringUtil.isEmptyOrSpaces(linkedText)) { renderer.append(" "); renderer.append(myLinkedText.getLinkText(), SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, this); } + renderer.append(myLinkedText.getTextAfter(), SimpleTextAttributes.REGULAR_ATTRIBUTES); } } \ No newline at end of file diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java new file mode 100644 index 000000000000..76578165b37c --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2014 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 com.intellij.dvcs.push.ui; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.tree.DefaultMutableTreeNode; + +public interface VcsLinkListener { + void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode); +} diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java new file mode 100644 index 000000000000..35c4989f160e --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java @@ -0,0 +1,70 @@ +/* + * Copyright 2000-2014 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 com.intellij.dvcs.push.ui; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VcsLinkedText { + + private static final Pattern HREF_PATTERN = Pattern.compile("([^<]*)"); + + @NotNull private String myTextBefore; + @NotNull private String myTextAfter; + @NotNull private String myHandledLink; + + @Nullable private final VcsLinkListener myLinkListener; + + public VcsLinkedText(@NotNull String text, @Nullable VcsLinkListener listener) { + Matcher aMatcher = HREF_PATTERN.matcher(text); + if (aMatcher.find()) { + myTextBefore = text.substring(0, aMatcher.start()); + myHandledLink = aMatcher.group(2); + myTextAfter = text.substring(aMatcher.end(), text.length()); + } + else { + myTextBefore = text; + myHandledLink = ""; + myTextAfter = ""; + } + myLinkListener = listener; + } + + @NotNull + public String getTextBefore() { + return myTextBefore; + } + + @NotNull + public String getTextAfter() { + return myTextAfter; + } + + @NotNull + public String getLinkText() { + return myHandledLink; + } + + public void hyperLinkActivate(@NotNull DefaultMutableTreeNode relatedNode) { + if (myLinkListener != null) { + myLinkListener.hyperlinkActivated(relatedNode); + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java index 0936d6a1bba8..00977ee31cb0 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java @@ -16,7 +16,6 @@ package org.zmlx.hg4idea.push; import com.intellij.dvcs.push.*; -import com.intellij.dvcs.push.ui.RepositoryNode; import com.intellij.dvcs.repo.Repository; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -32,8 +31,6 @@ import org.zmlx.hg4idea.util.HgChangesetUtil; import org.zmlx.hg4idea.util.HgErrorUtil; import org.zmlx.hg4idea.util.HgVersion; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -73,18 +70,12 @@ public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { for (String error : resultErrors) { if (HgErrorUtil.isAbortLine(error)) { if (HgErrorUtil.isAuthorizationError(error)) { - VcsError authorizationError = new VcsError(error, LOGIN_AND_REFRESH_LINK); - authorizationError.addClickListener(new TreeNodeLinkListener() { - @Override - public void onClick(@NotNull DefaultMutableTreeNode source) { - TreeNode parent = source.getParent(); - if (parent instanceof RepositoryNode) { - //todo change value to something special, or create force refreshNode method - ((RepositoryNode)parent).fireOnChange(((RepositoryNode)parent).getValue()); - } - } - } - ); + VcsError authorizationError = + new VcsError(error + "" + LOGIN_AND_REFRESH_LINK + "", new VcsErrorHandler() { + public void handleError(@NotNull CommitLoader commitLoader) { + commitLoader.reloadCommits(); + } + }); errors.add(authorizationError); } else {