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 3495cbb7cbe2..139d50421a47 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,8 +15,8 @@ */ package com.intellij.dvcs.push.ui; -import com.intellij.openapi.actionSystem.CommonShortcuts; -import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Condition; @@ -58,22 +58,23 @@ import java.util.List; public class PushLog extends JPanel implements DataProvider { - private final static String CONTEXT_MENU = "Vcs.Push.ContextMenu"; + private static final String CONTEXT_MENU = "Vcs.Push.ContextMenu"; private static final String START_EDITING = "startEditing"; private final ChangesBrowser myChangesBrowser; private final CheckboxTree myTree; private final MyTreeCellRenderer myTreeCellRenderer; private final JScrollPane myScrollPane; + private final VcsCommitInfoBalloon myBalloon; private boolean myShouldRepaint = false; private boolean mySyncStrategy; @Nullable private String mySyncRenderedText; private final boolean myAllowSyncStrategy; - public PushLog(Project project, final CheckedTreeNode root, final boolean allowSyncStrategy) { myAllowSyncStrategy = allowSyncStrategy; DefaultTreeModel treeModel = new DefaultTreeModel(root); treeModel.nodeStructureChanged(root); + final AnAction quickDocAction = ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC); myTreeCellRenderer = new MyTreeCellRenderer(); myTree = new CheckboxTree(myTreeCellRenderer, root) { @@ -99,7 +100,9 @@ public class PushLog extends JPanel implements DataProvider { return ""; } if (node instanceof TooltipNode) { - return ((TooltipNode)node).getTooltip(); + return KeymapUtil.createTooltipText( + ((TooltipNode)node).getTooltip() + + "

QuickDoc available", quickDocAction) + "

"; } return ""; } @@ -183,12 +186,13 @@ public class PushLog extends JPanel implements DataProvider { TreeUtil.collapseAll(myTree, 1); final VcsBranchEditorListener linkMouseListener = new VcsBranchEditorListener(myTreeCellRenderer); linkMouseListener.installOn(myTree); - + myBalloon = new VcsCommitInfoBalloon(myTree); myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); myTree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { updateChangesView(); + myBalloon.updateCommitDetails(); } }); myTree.addFocusListener(new FocusAdapter() { @@ -205,6 +209,9 @@ public class PushLog extends JPanel implements DataProvider { myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), START_EDITING); //override default tree behaviour. myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ""); + //String name="push.show.commit.details"; + MyShowCommitInfoAction showCommitInfoAction = new MyShowCommitInfoAction(); + showCommitInfoAction.registerCustomShortcutSet(quickDocAction.getShortcutSet(), myTree); ToolTipManager.sharedInstance().registerComponent(myTree); PopupHandler.installPopupHandler(myTree, VcsLogUiImpl.POPUP_ACTION_GROUP, CONTEXT_MENU); @@ -251,6 +258,18 @@ public class PushLog extends JPanel implements DataProvider { myTree.setRowHeight(0); } + private class MyShowCommitInfoAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + myBalloon.showCommitDetails(); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(getSelectedCommitNodes().size() == 1); + } + } + private void restoreSelection(@Nullable DefaultMutableTreeNode node) { if (node != null) { TreeUtil.selectNode(myTree, node); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsCommitInfoBalloon.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsCommitInfoBalloon.java new file mode 100644 index 000000000000..794d49bbe5a2 --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsCommitInfoBalloon.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2015 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 com.intellij.codeInsight.hint.HintUtil; +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.ui.popup.ComponentPopupBuilder; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.ui.HyperlinkAdapter; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.ui.UIUtil; +import com.intellij.xml.util.XmlStringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.HyperlinkEvent; +import javax.swing.tree.TreePath; +import java.awt.*; + +public class VcsCommitInfoBalloon { + private static final String EMPTY_COMMIT_INFO = "

No commit information found...

"; + + @NotNull private final JTree myTree; + @Nullable private JBPopup myBalloon; + @NotNull private final JEditorPane myEditorPane; + @NotNull private final ComponentPopupBuilder myPopupBuilder; + + public VcsCommitInfoBalloon(@NotNull JTree tree) { + myTree = tree; + myEditorPane = new JEditorPane(UIUtil.HTML_MIME, ""); + myEditorPane.setEditable(false); + myEditorPane.setBackground(HintUtil.INFORMATION_COLOR); + myEditorPane.setBorder(new EmptyBorder(2, 4, 2, 4)); + myEditorPane.addHyperlinkListener(new HyperlinkAdapter() { + @Override + protected void hyperlinkActivated(HyperlinkEvent e) { + BrowserUtil.browse(e.getURL()); + } + }); + myPopupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(myEditorPane, null); + myPopupBuilder.setCancelOnClickOutside(true).setResizable(true).setMovable(true).setRequestFocus(false) + .setMinSize(new Dimension(200, 80)); + } + + public void updateCommitDetails() { + if (myBalloon != null && myBalloon.isVisible()) { + TreePath[] selectionPaths = myTree.getSelectionPaths(); + if (selectionPaths == null || selectionPaths.length != 1) { + myBalloon.cancel(); + } + else { + Object node = selectionPaths[0].getLastPathComponent(); + myEditorPane.setText( + XmlStringUtil.wrapInHtml(node instanceof TooltipNode ? ((TooltipNode)node).getTooltip().replaceAll("\n", "
") : + EMPTY_COMMIT_INFO)); + myBalloon.setSize(myEditorPane.getPreferredSize()); + myBalloon.setLocation(calculateBestPopupLocation()); + } + } + } + + @NotNull + private Point calculateBestPopupLocation() { + Point defaultLocation = myTree.getLocationOnScreen(); + TreePath selectionPath = myTree.getSelectionPath(); + if (selectionPath == null) return defaultLocation; + Rectangle rectangle = myTree.getPathBounds(selectionPath); + if (rectangle == null) return defaultLocation; + Point location = rectangle.getLocation(); + SwingUtilities.convertPointToScreen(location, myTree); + return new Point(location.x, location.y + rectangle.height); + } + + private void createNewCommitInfoBalloon() { + myBalloon = myPopupBuilder.createPopup(); + } + + public void showCommitDetails() { + if (myBalloon == null || !myBalloon.isVisible()) { + createNewCommitInfoBalloon(); + myBalloon.show(new RelativePoint(calculateBestPopupLocation())); + } + updateCommitDetails(); + } +}