mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-239121 diff: fix title and notifications header layout
* Update layout to correctly handle gaps for invisible components (ex: hidden notification). * Fix invisible notifications: EditorNotificationPanel has minimum height of 0, which was used by previous MigLayout to give it zero height and force multiple panels to draw on top of each other. GitOrigin-RevId: 15b8741815b3ab6acc408289a4961d9ee778a1e7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f8da64a972
commit
4fe7571aad
@@ -16,7 +16,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="library" name="miglayout-swing" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.statistics" />
|
||||
<orderEntry type="module" module-name="intellij.platform.boot" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
|
||||
@@ -21,13 +21,13 @@ import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.diff.util.InvisibleWrapper;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import net.miginfocom.layout.CC;
|
||||
import net.miginfocom.layout.LC;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
class DiffContentPanel extends JPanel {
|
||||
@@ -71,15 +71,11 @@ class DiffContentPanel extends JPanel {
|
||||
@NotNull JComponent content,
|
||||
@NotNull JComponent bottomBreadcrumbs) {
|
||||
contentPanel.removeAll();
|
||||
|
||||
MigLayout mgr = new MigLayout(new LC().flowY().fill().hideMode(3)
|
||||
.insets("0").gridGapY("0"));
|
||||
contentPanel.setLayout(mgr);
|
||||
|
||||
contentPanel.add(title, new CC().growX().minWidth("0").gapY("0", String.valueOf(DiffUtil.TITLE_GAP)));
|
||||
contentPanel.add(topBreadcrumbs, new CC().growX().minWidth("0"));
|
||||
contentPanel.add(content, new CC().grow().push());
|
||||
contentPanel.add(bottomBreadcrumbs, new CC().growX().minWidth("0"));
|
||||
contentPanel.setLayout(new DiffContentLayout(title, topBreadcrumbs, content, bottomBreadcrumbs));
|
||||
contentPanel.add(title);
|
||||
contentPanel.add(topBreadcrumbs);
|
||||
contentPanel.add(content);
|
||||
contentPanel.add(bottomBreadcrumbs);
|
||||
}
|
||||
|
||||
public static void syncTitleHeights(@NotNull List<DiffContentPanel> panels) {
|
||||
@@ -96,4 +92,69 @@ class DiffContentPanel extends JPanel {
|
||||
initLayout(contentPanel, title, topBreadcrumb, contentPanel.myContent, contentPanel.myBottomBreadcrumbs);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DiffContentLayout extends AbstractLayoutManager {
|
||||
@NotNull private final JComponent myTitle;
|
||||
@NotNull private final JComponent myTopBreadcrumbs;
|
||||
@NotNull private final JComponent myContent;
|
||||
@NotNull private final JComponent myBottomBreadcrumbs;
|
||||
|
||||
DiffContentLayout(@NotNull JComponent title,
|
||||
@NotNull JComponent topBreadcrumbs,
|
||||
@NotNull JComponent content,
|
||||
@NotNull JComponent bottomBreadcrumbs) {
|
||||
myTitle = title;
|
||||
myTopBreadcrumbs = topBreadcrumbs;
|
||||
myContent = content;
|
||||
myBottomBreadcrumbs = bottomBreadcrumbs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
int totalWidth = 0;
|
||||
int totalHeight = 0;
|
||||
|
||||
for (JComponent component : Arrays.asList(myTitle, myTopBreadcrumbs, myContent, myBottomBreadcrumbs)) {
|
||||
Dimension size = getPreferredSize(component);
|
||||
|
||||
totalWidth = Math.max(size.width, totalWidth);
|
||||
totalHeight += size.height;
|
||||
|
||||
if (component == myTitle && size.height != 0) {
|
||||
totalHeight += DiffUtil.TITLE_GAP;
|
||||
}
|
||||
}
|
||||
|
||||
return new Dimension(totalWidth, totalHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(@NotNull Container parent) {
|
||||
int y = 0;
|
||||
|
||||
int width = parent.getWidth();
|
||||
int totalHeight = parent.getHeight();
|
||||
|
||||
Dimension titleSize = getPreferredSize(myTitle);
|
||||
Dimension topSize = getPreferredSize(myTopBreadcrumbs);
|
||||
Dimension bottomSize = getPreferredSize(myBottomBreadcrumbs);
|
||||
int bottomY = totalHeight - bottomSize.height;
|
||||
|
||||
myTitle.setBounds(0, y, width, titleSize.height);
|
||||
y += titleSize.height;
|
||||
if (titleSize.height != 0) y += DiffUtil.TITLE_GAP;
|
||||
|
||||
myTopBreadcrumbs.setBounds(0, y, width, topSize.height);
|
||||
y += topSize.height;
|
||||
|
||||
myContent.setBounds(0, y, width, Math.max(0, bottomY - y));
|
||||
|
||||
myBottomBreadcrumbs.setBounds(0, bottomY, width, bottomSize.height);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Dimension getPreferredSize(@NotNull JComponent component) {
|
||||
return component.isVisible() ? component.getPreferredSize() : new Dimension();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,21 +565,20 @@ public final class DiffUtil {
|
||||
private static JComponent createTitleWithNotifications(@Nullable DiffViewer viewer,
|
||||
@Nullable JComponent title,
|
||||
@NotNull DiffContent content) {
|
||||
List<JComponent> notifications = new ArrayList<>(createCustomNotifications(viewer, content));
|
||||
List<JComponent> components = new ArrayList<>();
|
||||
if (title != null) components.add(title);
|
||||
|
||||
components.addAll(createCustomNotifications(viewer, content));
|
||||
|
||||
if (content instanceof DocumentContent) {
|
||||
Document document = ((DocumentContent)content).getDocument();
|
||||
if (FileDocumentManager.getInstance().isPartialPreviewOfALargeFile(document)) {
|
||||
notifications.add(DiffNotifications.createNotification(DiffBundle.message("error.file.is.too.large.only.preview.is.loaded")));
|
||||
components.add(DiffNotifications.createNotification(DiffBundle.message("error.file.is.too.large.only.preview.is.loaded")));
|
||||
}
|
||||
}
|
||||
|
||||
if (notifications.isEmpty()) return title;
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout(0, TITLE_GAP));
|
||||
if (title != null) panel.add(title, BorderLayout.NORTH);
|
||||
panel.add(createStackedComponents(notifications, TITLE_GAP), BorderLayout.SOUTH);
|
||||
return panel;
|
||||
if (components.isEmpty()) return null;
|
||||
return createStackedComponents(components, TITLE_GAP);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -689,21 +688,18 @@ public final class DiffUtil {
|
||||
if (!ContainerUtil.exists(components, Conditions.notNull())) return components;
|
||||
List<JComponent> result = new ArrayList<>();
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
result.add(new SyncHeightComponent(components, i));
|
||||
JComponent component = components.get(i);
|
||||
result.add(new SyncHeightComponent(components, component));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JComponent createStackedComponents(@NotNull List<? extends JComponent> components, int gap) {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
for (int i = 0; i < components.size(); i++) {
|
||||
if (i != 0) panel.add(Box.createVerticalStrut(JBUIScale.scale(gap)));
|
||||
panel.add(components.get(i));
|
||||
public static JComponent createStackedComponents(@NotNull List<? extends JComponent> components, int vGap) {
|
||||
JPanel panel = new JPanel(new VerticalStackLayout(vGap));
|
||||
for (JComponent component : components) {
|
||||
panel.add(component);
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.diff.util;
|
||||
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -11,35 +12,11 @@ import java.util.List;
|
||||
public class SyncHeightComponent extends JPanel {
|
||||
@NotNull private final List<? extends JComponent> myComponents;
|
||||
|
||||
SyncHeightComponent(@NotNull List<? extends JComponent> components, int index) {
|
||||
super(new BorderLayout());
|
||||
myComponents = components;
|
||||
JComponent delegate = components.get(index);
|
||||
if (delegate != null) add(delegate, BorderLayout.CENTER);
|
||||
}
|
||||
SyncHeightComponent(@NotNull List<? extends JComponent> syncComponents, @Nullable JComponent component) {
|
||||
super(new SyncHeightLayout(syncComponents, component));
|
||||
myComponents = syncComponents;
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
Dimension size = super.getMinimumSize();
|
||||
size.height = getMaximumHeight(JComponent::getPreferredSize);
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
size.height = getMaximumHeight(JComponent::getPreferredSize);
|
||||
return size;
|
||||
}
|
||||
|
||||
private int getMaximumHeight(@NotNull Function<? super JComponent, ? extends Dimension> getter) {
|
||||
int height = 0;
|
||||
for (JComponent component : myComponents) {
|
||||
if (component != null) {
|
||||
height = Math.max(height, getter.fun(component).height);
|
||||
}
|
||||
}
|
||||
return height;
|
||||
if (component != null) add(component);
|
||||
}
|
||||
|
||||
public void revalidateAll() {
|
||||
@@ -47,4 +24,44 @@ public class SyncHeightComponent extends JPanel {
|
||||
if (component != null) component.revalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SyncHeightLayout extends AbstractLayoutManager {
|
||||
@NotNull private final List<? extends JComponent> mySyncComponents;
|
||||
@Nullable private final JComponent myComponent;
|
||||
|
||||
SyncHeightLayout(@NotNull List<? extends JComponent> syncComponents, @Nullable JComponent component) {
|
||||
mySyncComponents = syncComponents;
|
||||
myComponent = component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
int totalHeight = 0;
|
||||
|
||||
for (JComponent component : mySyncComponents) {
|
||||
Dimension size = getPreferredSize(component);
|
||||
totalHeight = Math.max(size.height, totalHeight);
|
||||
}
|
||||
|
||||
int width = getPreferredSize(myComponent).width;
|
||||
|
||||
return new Dimension(width, totalHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(@NotNull Container parent) {
|
||||
int width = parent.getWidth();
|
||||
int height = parent.getHeight();
|
||||
|
||||
if (myComponent == null) return;
|
||||
|
||||
Dimension size = getPreferredSize(myComponent);
|
||||
myComponent.setBounds(0, 0, width, Math.min(height, size.height));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Dimension getPreferredSize(@Nullable Component component) {
|
||||
return component != null && component.isVisible() ? component.getPreferredSize() : new Dimension();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.diff.util;
|
||||
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
class VerticalStackLayout extends AbstractLayoutManager {
|
||||
private final int myVGap;
|
||||
|
||||
VerticalStackLayout(int vGap) {
|
||||
myVGap = vGap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
int totalWidth = 0;
|
||||
int totalHeight = 0;
|
||||
|
||||
for (Component component : parent.getComponents()) {
|
||||
Dimension size = getPreferredSize(component);
|
||||
|
||||
totalWidth = Math.max(size.width, totalWidth);
|
||||
if (size.height != 0 && totalHeight != 0) totalHeight += myVGap;
|
||||
totalHeight += size.height;
|
||||
}
|
||||
|
||||
return new Dimension(totalWidth, totalHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(@NotNull Container parent) {
|
||||
int width = parent.getWidth();
|
||||
|
||||
int y = 0;
|
||||
for (Component component : parent.getComponents()) {
|
||||
Dimension size = getPreferredSize(component);
|
||||
|
||||
component.setBounds(0, y, width, size.height);
|
||||
if (size.height != 0) y += myVGap;
|
||||
y += size.height;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Dimension getPreferredSize(@NotNull Component component) {
|
||||
return component.isVisible() ? component.getPreferredSize() : new Dimension();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user