diff options
Diffstat (limited to 'platform/dvcs-impl/src/com/intellij/dvcs/push/ui')
6 files changed, 104 insertions, 145 deletions
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java index b5747de91bf7..aab70818082d 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java @@ -15,9 +15,12 @@ */ package com.intellij.dvcs.push.ui; -import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.dvcs.push.OutgoingResult; import org.jetbrains.annotations.NotNull; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + public interface EditableTreeNode extends CustomRenderedTreeNode { void fireOnChange(); @@ -28,8 +31,5 @@ public interface EditableTreeNode extends CustomRenderedTreeNode { void stopLoading(); - @NotNull - ProgressIndicator startLoading(); - - String getValue(); + void startLoading(@NotNull Future<AtomicReference<OutgoingResult>> future); } 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 0b4bcb0fbef0..1539b94216c0 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 @@ -15,6 +15,7 @@ */ package com.intellij.dvcs.push.ui; +import com.intellij.dvcs.push.PushTargetPanel; import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.actionSystem.DataSink; @@ -25,7 +26,10 @@ import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser; import com.intellij.openapi.vcs.changes.ui.ChangesBrowser; -import com.intellij.ui.*; +import com.intellij.ui.CheckboxTree; +import com.intellij.ui.CheckedTreeNode; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBTextField; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.tree.TreeUtil; @@ -37,7 +41,10 @@ import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -45,17 +52,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EventObject; -import java.util.concurrent.locks.ReentrantReadWriteLock; public class PushLog extends JPanel implements TypeSafeDataProvider { - private final ReentrantReadWriteLock TREE_CONSTRUCTION_LOCK = new ReentrantReadWriteLock(); - private static final String START_EDITING = "startEditing"; private final ChangesBrowser myChangesBrowser; private final CheckboxTree myTree; private final MyTreeCellRenderer myTreeCellRenderer; - //private final AtomicBoolean myIgnoreStopEditing = new AtomicBoolean(false); + private boolean myEditingSucceeded; public PushLog(Project project, CheckedTreeNode root) { DefaultTreeModel treeModel = new DefaultTreeModel(root); @@ -89,6 +93,23 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { } return ""; } + + @Override + public boolean stopEditing() { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent(); + if (node instanceof EditableTreeNode) { + JComponent editedComponent = (JComponent)node.getUserObject(); + InputVerifier verifier = editedComponent.getInputVerifier(); + if (verifier != null && !verifier.verify(editedComponent)) return false; + } + myEditingSucceeded = true; + try { + return super.stopEditing(); + } + finally { + myEditingSucceeded = false; + } + } }; myTree.setEditable(true); MyTreeCellEditor treeCellEditor = new MyTreeCellEditor(new JBTextField()); @@ -140,6 +161,9 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { } }); myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), START_EDITING); + //override default tree behaviour. + myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ""); + myTree.setRowHeight(0); ToolTipManager.sharedInstance().registerComponent(myTree); @@ -197,8 +221,14 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - if (e.getKeyCode() == KeyEvent.VK_ENTER && myTree.isEditing()) { - myTree.stopEditing(); + if (e.getKeyCode() == KeyEvent.VK_ENTER && pressed) { + if (myTree.isEditing()) { + myTree.stopEditing(); + } + else { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent(); + myTree.startEditingAtPath(TreeUtil.getPathFromRoot(node)); + } return true; } return super.processKeyBinding(ks, e, condition, pressed); @@ -239,7 +269,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { Object tag = me.getClickCount() >= clickCountToStart ? PushLogTreeUtil.getTagAtForRenderer(myTreeCellRenderer, me) : null; - return tag instanceof EditorTextField; + return tag instanceof PushTargetPanel; } //if keyboard event - then anEvent will be null =( See BasicTreeUi TreePath treePath = myTree.getAnchorSelectionPath(); @@ -251,7 +281,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { //Implement the one CellEditor method that AbstractCellEditor doesn't. public Object getCellEditorValue() { - return ((RepositoryWithBranchPanel)editorComponent).getRemoteTargetName(); + return myEditingSucceeded ? ((RepositoryWithBranchPanel)editorComponent).getEditableValue() : null; } } @@ -285,34 +315,19 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { public void setChildren(DefaultMutableTreeNode parentNode, @NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes, boolean shouldExpand) { - try { - TREE_CONSTRUCTION_LOCK.writeLock().lock(); - parentNode.removeAllChildren(); - for (DefaultMutableTreeNode child : childrenNodes) { - parentNode.add(child); - } - final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel()); - model.nodeStructureChanged(parentNode); - TreePath path = TreeUtil.getPathFromRoot(parentNode); - //myIgnoreStopEditing.set(true); - if (shouldExpand) { - myTree.expandPath(path); - } - else { - myTree.collapsePath(path); - } + parentNode.removeAllChildren(); + for (DefaultMutableTreeNode child : childrenNodes) { + parentNode.add(child); } - finally { - TREE_CONSTRUCTION_LOCK.writeLock().unlock(); - //myIgnoreStopEditing.set(false); + final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel()); + model.nodeStructureChanged(parentNode); + TreePath path = TreeUtil.getPathFromRoot(parentNode); + if (shouldExpand) { + myTree.expandPath(path); } - } - - public void startEditNode(@NotNull TreeNode node) { - TreePath path = TreeUtil.getPathFromRoot(node); - if (!myTree.isEditing()) { - myTree.setSelectionPath(path); - myTree.startEditingAtPath(path); + else { + myTree.collapsePath(path); } } + } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java index 05e752c4be85..4808064f5c8d 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java @@ -15,29 +15,26 @@ */ package com.intellij.dvcs.push.ui; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.ui.*; +import com.intellij.dvcs.push.OutgoingResult; +import com.intellij.dvcs.push.PushTargetPanel; +import com.intellij.ui.CheckedTreeNode; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; -import java.util.ArrayList; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode, Comparable<RepositoryNode> { @NotNull private final RepositoryWithBranchPanel myRepositoryPanel; - @NotNull protected SimpleColoredText myTargetPresentation; - private ProgressIndicator myCurrentIndicator; + private Future<AtomicReference<OutgoingResult>> myFuture; - public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel, @NotNull SimpleColoredText targetPresentation) { + public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) { super(repositoryPanel); myRepositoryPanel = repositoryPanel; - myTargetPresentation = targetPresentation; - } - - public void setTargetPresentation(@NotNull SimpleColoredText targetPresentation) { - myTargetPresentation = targetPresentation; } public boolean isCheckboxVisible() { @@ -51,32 +48,18 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode, renderer.appendFixedTextFragmentWidth(120); renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - EditorTextField textField = myRepositoryPanel.getRemoteTextFiled(); - renderTargetName(renderer, textField); - Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField); + PushTargetPanel pushTargetPanel = myRepositoryPanel.getTargetPanel(); + pushTargetPanel.render(renderer); + Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(pushTargetPanel); renderer.setBorder(new EmptyBorder(insets)); } - protected void renderTargetName(@NotNull ColoredTreeCellRenderer renderer, @NotNull EditorTextField textField) { - ArrayList<String> strings = myTargetPresentation.getTexts(); - ArrayList<SimpleTextAttributes> attributes = myTargetPresentation.getAttributes(); - for (int i = 0; i < strings.size(); i++) { - renderer.append(strings.get(i), attributes.get(i), textField); - } - } - @Override public Object getUserObject() { return myRepositoryPanel; } @Override - @NotNull - public String getValue() { - return myRepositoryPanel.getRemoteTargetName(); - } - - @Override public void fireOnChange() { myRepositoryPanel.fireOnChange(); } @@ -93,15 +76,14 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode, @Override public void stopLoading() { - if (myCurrentIndicator != null && myCurrentIndicator.isRunning()) { - myCurrentIndicator.cancel(); + if (myFuture != null && !myFuture.isDone()) { + myFuture.cancel(true); } } @Override - @NotNull - public ProgressIndicator startLoading() { - return myCurrentIndicator = new EmptyProgressIndicator(); + public void startLoading(@NotNull Future<AtomicReference<OutgoingResult>> future) { + myFuture = future; } public int compareTo(@NotNull RepositoryNode repositoryNode) { 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 cd93d0653c36..29a32237ca3a 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 @@ -15,18 +15,15 @@ */ package com.intellij.dvcs.push.ui; +import com.intellij.dvcs.push.PushTarget; +import com.intellij.dvcs.push.PushTargetPanel; import com.intellij.dvcs.push.RepositoryNodeListener; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.project.Project; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.SimpleTextAttributes; -import com.intellij.ui.TextFieldWithAutoCompletion; -import com.intellij.ui.TextFieldWithAutoCompletionListProvider; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -34,23 +31,20 @@ import javax.swing.tree.TreeCellRenderer; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; import java.util.List; -public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCellRenderer { +public class RepositoryWithBranchPanel<T extends PushTarget> extends NonOpaquePanel implements TreeCellRenderer { private final JBCheckBox myRepositoryCheckbox; - private final TextFieldWithAutoCompletion myDestBranchTextField; + private final PushTargetPanel<T> myDestPushTargetPanelComponent; private final JBLabel myLocalBranch; private final JLabel myArrowLabel; private final JLabel myRepositoryLabel; private final ColoredTreeCellRenderer myTextRenderer; - @NotNull private final List<RepositoryNodeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private String myOldDestination; + @NotNull private final List<RepositoryNodeListener<T>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - public RepositoryWithBranchPanel(Project project, @NotNull String repoName, - @NotNull String sourceName, String targetName, @NotNull final List<String> targetVariants) { + public RepositoryWithBranchPanel(@NotNull String repoName, + @NotNull String sourceName, @NotNull PushTargetPanel<T> destPushTargetPanelComponent) { super(); setLayout(new BorderLayout()); myRepositoryCheckbox = new JBCheckBox(); @@ -65,37 +59,7 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel myRepositoryLabel = new JLabel(repoName); myLocalBranch = new JBLabel(sourceName); myArrowLabel = new JLabel(" -> "); - myOldDestination = targetName; - TextFieldWithAutoCompletionListProvider<String> provider = - new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null) { - @Override - public int compare(String item1, String item2) { - return Integer.valueOf(ContainerUtil.indexOf(targetVariants, item1)).compareTo(ContainerUtil.indexOf(targetVariants, item2)); - } - }; - myDestBranchTextField = new TextFieldWithAutoCompletion<String>(project, provider, true, targetName) { - - @Override - public boolean shouldHaveBorder() { - return false; - } - - @Override - protected void updateBorder(@NotNull final EditorEx editor) { - } - }; - myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder()); - myDestBranchTextField.setOneLineMode(true); - myDestBranchTextField.setOpaque(true); - FocusAdapter focusListener = new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - myDestBranchTextField.selectAll(); - } - }; - myDestBranchTextField.addFocusListener(focusListener); - addFocusListener(focusListener); - + myDestPushTargetPanelComponent = destPushTargetPanelComponent; myTextRenderer = new ColoredTreeCellRenderer() { public void customizeCellRenderer(@NotNull JTree tree, Object value, @@ -115,7 +79,7 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel add(myRepositoryCheckbox, BorderLayout.WEST); JPanel panel = new NonOpaquePanel(new BorderLayout()); panel.add(myTextRenderer, BorderLayout.WEST); - panel.add(myDestBranchTextField, BorderLayout.CENTER); + panel.add(myDestPushTargetPanelComponent, BorderLayout.CENTER); add(panel, BorderLayout.CENTER); } @@ -132,15 +96,6 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel return myArrowLabel.getText(); } - public TextFieldWithAutoCompletion getRemoteTextFiled() { - return myDestBranchTextField; - } - - @NotNull - public String getRemoteTargetName() { - return myDestBranchTextField.getText(); - } - @Override public Component getTreeCellRendererComponent(JTree tree, Object value, @@ -168,20 +123,20 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel if (bounds != null) { setPreferredSize(new Dimension(tree.getWidth() - bounds.x, bounds.height)); } - myDestBranchTextField.grabFocus(); - myDestBranchTextField.requestFocus(); + myDestPushTargetPanelComponent.grabFocus(); + myDestPushTargetPanelComponent.requestFocus(); revalidate(); return this; } - public void addRepoNodeListener(@NotNull RepositoryNodeListener listener) { + public void addRepoNodeListener(@NotNull RepositoryNodeListener<T> listener) { myListeners.add(listener); } public void fireOnChange() { - myOldDestination = myDestBranchTextField.getText(); - for (RepositoryNodeListener listener : myListeners) { - listener.onTargetChanged(myOldDestination); + myDestPushTargetPanelComponent.fireOnChange(); + for (RepositoryNodeListener<T> listener : myListeners) { + listener.onTargetChanged(myDestPushTargetPanelComponent.getValue()); } } @@ -192,7 +147,15 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel } public void fireOnCancel() { - myDestBranchTextField.setText(myOldDestination); + myDestPushTargetPanelComponent.fireOnCancel(); + } + + public PushTargetPanel getTargetPanel() { + return myDestPushTargetPanelComponent; + } + + public T getEditableValue() { + return myDestPushTargetPanelComponent.getValue(); } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java index 81fb2bd1a9d0..8506e1d50fea 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java @@ -15,9 +15,8 @@ */ package com.intellij.dvcs.push.ui; +import com.intellij.dvcs.push.PushTargetPanel; import com.intellij.ui.ColoredTreeCellRenderer; -import com.intellij.ui.EditorTextField; -import com.intellij.ui.SimpleColoredText; import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.annotations.NotNull; @@ -29,8 +28,8 @@ public class SingleRepositoryNode extends RepositoryNode { @NotNull private final RepositoryWithBranchPanel myRepositoryPanel; - public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel, @NotNull SimpleColoredText customTargetPresentation) { - super(repositoryPanel, customTargetPresentation); + public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) { + super(repositoryPanel); myRepositoryPanel = repositoryPanel; } @@ -43,9 +42,9 @@ public class SingleRepositoryNode extends RepositoryNode { public void render(@NotNull ColoredTreeCellRenderer renderer) { renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - EditorTextField textField = myRepositoryPanel.getRemoteTextFiled(); - renderTargetName(renderer, textField); - Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField); + PushTargetPanel pushTargetPanel = myRepositoryPanel.getTargetPanel(); + pushTargetPanel.render(renderer); + Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(pushTargetPanel); renderer.setBorder(new EmptyBorder(insets)); } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java index d8e35fd25d53..0b3df11db78a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java @@ -15,9 +15,9 @@ */ package com.intellij.dvcs.push.ui; +import com.intellij.dvcs.push.PushTargetPanel; import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase; import com.intellij.ui.CheckboxTree; -import com.intellij.ui.EditorTextField; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,7 +35,7 @@ public class VcsBranchEditorListener extends LinkMouseListenerBase { public void mouseMoved(MouseEvent e) { Component component = (Component)e.getSource(); Object tag = getTagAt(e); - if (tag != null && tag instanceof EditorTextField) { + if (tag != null && tag instanceof PushTargetPanel) { component.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); } else if (tag != null && tag instanceof TextWithLinkNode) { |