diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/ThreeDiffSplitter.java b/platform/diff-impl/src/com/intellij/diff/tools/util/ThreeDiffSplitter.java index ba28d96c5caf..82231b8566d6 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/ThreeDiffSplitter.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/ThreeDiffSplitter.java @@ -17,27 +17,39 @@ package com.intellij.diff.tools.util; import com.intellij.diff.tools.util.DiffSplitter.Painter; import com.intellij.diff.util.Side; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.icons.AllIcons; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.MouseEvent; import java.util.List; public class ThreeDiffSplitter extends JPanel { private static final int DIVIDER_WIDTH = 30; - @NotNull private final List myDividers; @NotNull private final List myContents; + @NotNull private final Divider myDivider1; + @NotNull private final Divider myDivider2; + + private float myProportion1; // first size divided by (first + second + third) + private float myProportion2; // third size divided by (first + second + third) public ThreeDiffSplitter(@NotNull List components) { - myDividers = ContainerUtil.list(new Divider(), new Divider()); + assert components.size() == 3; myContents = components; + myDivider1 = new Divider(Side.LEFT); + myDivider2 = new Divider(Side.RIGHT); - addAll(myContents); - addAll(myDividers); + add(myDivider1); + add(myDivider2); + for (JComponent content : myContents) { + add(content); + } + + resetProportions(); } @CalledInAwt @@ -56,32 +68,44 @@ public class ThreeDiffSplitter extends JPanel { @NotNull private Divider getDivider(@NotNull Side side) { - return myDividers.get(side.getIndex()); + return side.select(myDivider1, myDivider2); } - private void addAll(@NotNull List components) { - for (JComponent component : components) { - add(component, -1); - } + private void resetProportions() { + myProportion1 = myProportion2 = 1f / 3; + } + + private void setProportion(float proportion, @NotNull Side side) { + proportion = Math.min(1f, Math.max(0f, proportion)); + float otherProportion = side.select(myProportion2, myProportion1); + otherProportion = Math.min(otherProportion, 1f - proportion); + + myProportion1 = side.select(proportion, otherProportion); + myProportion2 = side.select(otherProportion, proportion); } @Override public void doLayout() { int width = getWidth(); int height = getHeight(); - int panelWidth = (width - DIVIDER_WIDTH * 2) / 3; + + int dividersTotalWidth = DIVIDER_WIDTH * 2; + int contentsTotalWidth = Math.max(width - dividersTotalWidth, 0); + + JComponent[] components = new JComponent[]{myContents.get(0), myDivider1, myContents.get(1), myDivider2, myContents.get(2)}; + int[] contentWidths = new int[5]; + contentWidths[1] = DIVIDER_WIDTH; // divider1 + contentWidths[3] = DIVIDER_WIDTH; // divider2 + contentWidths[0] = (int)(contentsTotalWidth * myProportion1); // content1 + contentWidths[4] = (int)(contentsTotalWidth * myProportion2); // content3 + contentWidths[2] = Math.max(contentsTotalWidth - contentWidths[0] - contentWidths[4], 0); // content2 + int x = 0; - for (int i = 0; i < myContents.size(); i++) { - JComponent component = myContents.get(i); - component.setBounds(x, 0, panelWidth, height); + for (int i = 0; i < 5; i++) { + JComponent component = components[i]; + component.setBounds(x, 0, contentWidths[i], height); component.validate(); - x += panelWidth; - if (i < myDividers.size()) { - JComponent divider = myDividers.get(i); - divider.setBounds(x, 0, DIVIDER_WIDTH, height); - divider.validate(); - x += DIVIDER_WIDTH; - } + x += contentWidths[i]; } } @@ -109,12 +133,21 @@ public class ThreeDiffSplitter extends JPanel { return new Dimension(width, height); } - private static class Divider extends JComponent { + private class Divider extends JPanel { + @NotNull private final Side mySide; @Nullable private Painter myPainter; + public Divider(@NotNull Side side) { + super(new GridBagLayout()); + mySide = side; + enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK); + setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); + add(new JLabel(AllIcons.General.SplitGlueH), new GridBagConstraints()); + } + @Override - public void paint(Graphics g) { - super.paint(g); + protected void paintComponent(Graphics g) { + super.paintComponent(g); if (myPainter != null) myPainter.paint(g, this); } @@ -122,5 +155,32 @@ public class ThreeDiffSplitter extends JPanel { public void setPainter(@Nullable Painter painter) { myPainter = painter; } + + @Override + protected void processMouseMotionEvent(MouseEvent e) { + super.processMouseMotionEvent(e); + if (e.getID() == MouseEvent.MOUSE_DRAGGED) { + int totalWidth = ThreeDiffSplitter.this.getWidth(); + if (totalWidth > 0) { + Point point = SwingUtilities.convertPoint(this, e.getPoint(), ThreeDiffSplitter.this); + float proportion = (float)mySide.select(point.x, totalWidth - point.x) / (float)totalWidth; + setProportion(proportion, mySide); + + revalidate(); + repaint(); + } + } + } + + @Override + protected void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2) { + resetProportions(); + + revalidate(); + repaint(); + } + } } }