IDEA-118383 Git: Contained in branches pane is not scrollable
authorVassiliy.Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Thu, 9 Oct 2014 12:02:45 +0000 (16:02 +0400)
committerVassiliy.Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Thu, 9 Oct 2014 12:03:07 +0000 (16:03 +0400)
platform/util/src/com/intellij/util/ui/UIUtil.java
platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java

index 66adb1ed0952a1a13bba533178a749ac90706a71..ede4558ab55b8d8c3163b48b819485d9b6b30331 100644 (file)
@@ -1782,12 +1782,21 @@ public class UIUtil {
 
   @Nullable
   public static Component findNearestOpaque(JComponent c) {
+    return findParentByCondition(c, new Condition<Component>() {
+      @Override
+      public boolean value(Component component) {
+        return component.isOpaque();
+      }
+    });
+  }
+
+  @Nullable
+  public static Component findParentByCondition(@NotNull JComponent c, Condition<Component> condition) {
     Component eachParent = c;
     while (eachParent != null) {
-      if (eachParent.isOpaque()) return eachParent;
+      if (condition.value(eachParent)) return eachParent;
       eachParent = eachParent.getParent();
     }
-
     return null;
   }
 
@@ -3042,4 +3051,25 @@ public class UIUtil {
 
     textField.setColumns(4);
   }
+
+  public static <T> Border makeChameleonBorder(final Border border, final Condition<T> conditionToShow, final T checker) {
+    return new Border() {
+      @Override
+      public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+        if (conditionToShow.value(checker)) {
+          border.paintBorder(c, g, x, y, width, height);
+        }
+      }
+
+      @Override
+      public Insets getBorderInsets(Component c) {
+        return border.getBorderInsets(c);
+      }
+
+      @Override
+      public boolean isBorderOpaque() {
+        return border.isBorderOpaque() && conditionToShow.value(checker);
+      }
+    };
+  }
 }
index 4f255ed6cd7f301751f479a7566c703d6e329635..4049bceb80bc381a50f2acd54d7d12a066f3c591 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.vcs.log.ui.frame;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.progress.util.ProgressWindow;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -27,6 +28,7 @@ import com.intellij.ui.ScrollPaneFactory;
 import com.intellij.ui.components.JBLabel;
 import com.intellij.ui.components.JBLoadingPanel;
 import com.intellij.ui.components.JBTextField;
+import com.intellij.ui.components.panels.NonOpaquePanel;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.text.DateFormatUtil;
 import com.intellij.util.ui.AsyncProcessIcon;
@@ -41,12 +43,10 @@ import com.intellij.vcs.log.printer.idea.PrintParameters;
 import com.intellij.vcs.log.ui.VcsLogColorManager;
 import com.intellij.vcs.log.ui.render.RefPainter;
 import com.intellij.vcs.log.ui.tables.GraphTableModel;
-import net.miginfocom.swing.MigLayout;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import javax.swing.border.Border;
 import javax.swing.border.LineBorder;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -69,7 +69,8 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
   @NotNull private final VcsLogGraphTable myGraphTable;
 
   @NotNull private final RefsPanel myRefsPanel;
-  @NotNull private final DataPanel myDataPanel;
+  @NotNull private final DataPanel myHashAuthorPanel;
+  @NotNull private final DataPanel myMessageDataPanel;
   @NotNull private final ContainingBranchesPanel myContainingBranchesPanel;
   @NotNull private final MessagePanel myMessagePanel;
   @NotNull private final JBLoadingPanel myLoadingPanel;
@@ -78,18 +79,20 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
 
   DetailsPanel(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogGraphTable graphTable, @NotNull VcsLogColorManager colorManager,
                @NotNull VisiblePack initialDataPack) {
-    super(new CardLayout());
     myLogDataHolder = logDataHolder;
     myGraphTable = graphTable;
     myDataPack = initialDataPack;
 
     myRefsPanel = new RefsPanel(colorManager);
-    myDataPanel = new DataPanel(logDataHolder.getProject());
-    myContainingBranchesPanel = new ContainingBranchesPanel();
-    myMessagePanel = new MessagePanel();
+    myHashAuthorPanel = new DataPanel(logDataHolder.getProject(), false) {
+      @Override
+      public Dimension getPreferredSize() {
+        return super.getPreferredSize();
+      }
+    };
 
     final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane();
-    JPanel content = new JPanel(new MigLayout("flowy, ins 0, fill, hidemode 3")) {
+    myMessageDataPanel = new DataPanel(logDataHolder.getProject(), true) {
       @Override
       public Dimension getPreferredSize() {
         Dimension size = super.getPreferredSize();
@@ -97,19 +100,31 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
         return size;
       }
     };
-    content.setOpaque(false);
-    scrollPane.setViewportView(content);
-    content.add(myRefsPanel, "shrinky, pushx, growx");
-    content.add(myDataPanel, "growy, push");
-    content.add(myContainingBranchesPanel, "shrinky, pushx, growx");
-    content.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+    scrollPane.setViewportView(myMessageDataPanel);
+    scrollPane.setBorder(UIUtil.makeChameleonBorder(scrollPane.getBorder(), new Condition<JScrollBar>() {
+      @Override
+      public boolean value(JScrollBar bar) {
+        return bar != null && bar.isVisible();
+      }
+    }, scrollPane.getVerticalScrollBar()));
 
-    myLoadingPanel = new JBLoadingPanel(new BorderLayout(), logDataHolder, ProgressWindow.DEFAULT_PROGRESS_DIALOG_POSTPONE_TIME_MILLIS);
-    myLoadingPanel.add(scrollPane);
+    myContainingBranchesPanel = new ContainingBranchesPanel();
+    myMessagePanel = new MessagePanel();
 
+    myLoadingPanel = new JBLoadingPanel(new BorderLayout(), logDataHolder, ProgressWindow.DEFAULT_PROGRESS_DIALOG_POSTPONE_TIME_MILLIS);
+    JPanel header = new NonOpaquePanel(new BorderLayout());
+    header.add(myRefsPanel, BorderLayout.NORTH);
+    header.add(myHashAuthorPanel, BorderLayout.SOUTH);
+    myLoadingPanel.add(header, BorderLayout.NORTH);
+    myLoadingPanel.add(scrollPane, BorderLayout.CENTER);
+    myLoadingPanel.add(myContainingBranchesPanel, BorderLayout.SOUTH);
+    myLoadingPanel.setBackground(UIUtil.getTableBackground());
+
+    setLayout(new CardLayout());
     add(myLoadingPanel, STANDARD_LAYER);
     add(myMessagePanel, MESSAGE_LAYER);
 
+    setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
     setBackground(UIUtil.getTableBackground());
     showMessage("No commits selected");
   }
@@ -139,12 +154,14 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
       }
       if (commitData instanceof LoadingDetails) {
         myLoadingPanel.startLoading();
-        myDataPanel.setData(null);
+        myHashAuthorPanel.setData(null);
+        myMessageDataPanel.setData(null);
         myRefsPanel.setRefs(Collections.<VcsRef>emptyList());
       }
       else {
         myLoadingPanel.stopLoading();
-        myDataPanel.setData(commitData);
+        myHashAuthorPanel.setData(commitData);
+        myMessageDataPanel.setData(commitData);
         myRefsPanel.setRefs(sortRefs(hash, commitData.getRoot()));
       }
 
@@ -171,9 +188,11 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
   private static class DataPanel extends JEditorPane {
 
     @NotNull private final Project myProject;
+    private final boolean myMessageMode;
 
-    DataPanel(@NotNull Project project) {
+    DataPanel(@NotNull Project project, boolean messageMode) {
       super(UIUtil.HTML_MIME, "");
+      myMessageMode = messageMode;
       setEditable(false);
       myProject = project;
       addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
@@ -185,10 +204,25 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
         setText("");
       }
       else {
-        String body = getHashText(commit) + "<br/>" + getAuthorText(commit) + "<p>" + getMessageText(commit) + "</p>";
+        String body;
+        if (myMessageMode) {
+          body = getMessageText(commit);
+        } else {
+          body = commit.getId().asString() + "<br/>" + getAuthorText(commit);
+        }
         setText("<html><head>" + UIUtil.getCssFontDeclaration(UIUtil.getLabelFont()) + "</head><body>" + body + "</body></html>");
         setCaretPosition(0);
       }
+      revalidate();
+      repaint();
+    }
+
+    @Override
+    public Dimension getPreferredSize() {
+      Dimension size = super.getPreferredSize();
+      int h = getFontMetrics(getFont()).getHeight();
+      size.height = Math.max(size.height, myMessageMode ? 5 * h : 2 * h);
+      return size;
     }
 
     private String getMessageText(VcsFullCommitDetails commit) {
@@ -200,10 +234,6 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
              IssueLinkHtmlRenderer.formatTextWithLinks(myProject, description);
     }
 
-    private static String getHashText(VcsFullCommitDetails commit) {
-      return commit.getId().asString();
-    }
-
     private static String getAuthorText(VcsFullCommitDetails commit) {
       String authorText = commit.getAuthor().getName() + " at " + DateFormatUtil.formatDateTime(commit.getAuthorTime());
       if (!commit.getAuthor().equals(commit.getCommitter())) {
@@ -225,7 +255,7 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
 
   private static class ContainingBranchesPanel extends JPanel {
 
-    private final JComponent myLoadingIcon;
+    private final JComponent myLoadingComponent;
     private final JTextField myBranchesList;
 
     ContainingBranchesPanel() {
@@ -235,7 +265,9 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
           return UIUtil.getLabelFont().deriveFont(Font.ITALIC);
         }
       };
-      myLoadingIcon = new AsyncProcessIcon("Loading...");
+      myLoadingComponent = new NonOpaquePanel(new BorderLayout());
+      myLoadingComponent.add(new AsyncProcessIcon("Loading..."), BorderLayout.WEST);
+      myLoadingComponent.add(Box.createHorizontalGlue(), BorderLayout.CENTER);
       myBranchesList = new JBTextField("");
       myBranchesList.setEditable(false);
       myBranchesList.setBorder(IdeBorderFactory.createEmptyBorder()); // setting border to null may mean "use default border" while setting empty border means we do not want a border
@@ -248,30 +280,24 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
       }
 
       setOpaque(false);
-      setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
-      add(label);
-      add(myLoadingIcon);
-      add(myBranchesList);
-      add(Box.createHorizontalGlue());
+      setLayout(new BorderLayout());
+      add(label, BorderLayout.WEST);
+      add(Box.createHorizontalGlue(), BorderLayout.EAST);
     }
 
     void setBranches(@Nullable List<String> branches) {
       if (branches == null) {
-        myLoadingIcon.setVisible(true);
-        myBranchesList.setVisible(false);
+        remove(myBranchesList);
+        add(myLoadingComponent, BorderLayout.CENTER);
       }
       else {
-        myLoadingIcon.setVisible(false);
-        myBranchesList.setVisible(true);
-        myBranchesList.setText(getContainedBranchesText(branches));
+        remove(myLoadingComponent);
+        myBranchesList.setText(StringUtil.join(branches, ", "));
+        add(myBranchesList, BorderLayout.CENTER);
       }
+      revalidate();
+      repaint();
     }
-
-    @NotNull
-    private static String getContainedBranchesText(@NotNull List<String> branches) {
-      return StringUtil.join(branches, ", ");
-    }
-
   }
 
   private static class RefsPanel extends JPanel {
@@ -299,7 +325,7 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
     }
   }
 
-  private static class MessagePanel extends JPanel {
+  private static class MessagePanel extends NonOpaquePanel {
 
     private final JLabel myLabel;