IDEA-149395 Fix viewport to support translucent scroll bars

This commit is contained in:
Sergey Malenkov
2016-01-12 22:44:44 +03:00
parent 3e5c5d421d
commit 5f57460d2c
2 changed files with 136 additions and 2 deletions
@@ -16,6 +16,9 @@
package com.intellij.ui.components;
import com.intellij.openapi.ui.TypingTarget;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.components.JBScrollPane.Alignment;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
@@ -32,6 +35,20 @@ public class JBViewport extends JViewport implements ZoomableViewport {
@Override
public void layoutContainer(Container parent) {
if (parent instanceof JViewport && Registry.is("ide.scroll.new.layout")) {
JViewport viewport = (JViewport)parent;
Component view = viewport.getView();
if (view != null) {
JScrollPane pane = getScrollPane(viewport);
if (pane != null) {
doLayout(pane, viewport, view);
}
else {
super.layoutContainer(parent);
}
}
return;
}
JBViewport viewport = (JBViewport)parent;
Component view = viewport.getView();
JBScrollPane scrollPane = UIUtil.getParentOfType(JBScrollPane.class, parent);
@@ -155,4 +172,120 @@ public class JBViewport extends JViewport implements ZoomableViewport {
public boolean isPaintingNow() {
return myPaintingNow;
}
@Override
public Color getBackground() {
Component view = getView();
return view != null && view.isBackgroundSet()
? view.getBackground()
: super.getBackground();
}
@Override
public Dimension getExtentSize() {
Dimension size = super.getExtentSize();
if (SystemInfo.isMac) return size;
JScrollPane pane = getScrollPane(this);
if (pane != null) {
JScrollBar vsb = pane.getVerticalScrollBar();
if (null != getAlignment(vsb)) {
int width = vsb.getWidth();
if (size.width > width) size.width -= width;
}
JScrollBar hsb = pane.getHorizontalScrollBar();
if (null != getAlignment(hsb)) {
int height = hsb.getHeight();
if (size.height > height) size.height -= height;
}
}
return size;
}
/**
* Returns the alignment of the specified scroll bar
* if and only if the specified scroll bar
* is located over the corresponding viewport.
*
* @param bar the scroll bar to process
* @return the scroll bar alignment or {@code null}
*/
private static Alignment getAlignment(JScrollBar bar) {
if (bar != null && bar.isVisible() && !bar.isOpaque()) {
Object property = bar.getClientProperty(Alignment.class);
if (property instanceof Alignment) return (Alignment)property;
}
return null;
}
/**
* Returns the parent scroll pane of the specified viewport
* if and only if the specified viewport is a main viewport.
*
* @param viewport the viewport to process
* @return the parent scroll pane or {@code null}
*/
private static JScrollPane getScrollPane(JViewport viewport) {
Container parent = viewport.getParent();
if (parent instanceof JScrollPane) {
JScrollPane pane = (JScrollPane)parent;
if (viewport == pane.getViewport()) return pane;
}
return null;
}
private static void doLayout(JScrollPane pane, JViewport viewport, Component view) {
Dimension actualSize = viewport.getSize();
Dimension extentSize = viewport.getExtentSize();
Dimension viewPreferredSize = view.getPreferredSize();
Dimension viewSize = new Dimension(viewPreferredSize);
Point viewPosition = viewport.getViewPosition();
Scrollable scrollable = null;
if (view instanceof Scrollable) {
scrollable = (Scrollable)view;
if (scrollable.getScrollableTracksViewportWidth()) viewSize.width = actualSize.width;
if (scrollable.getScrollableTracksViewportHeight()) viewSize.height = actualSize.height;
}
// If the new viewport size would leave empty space to the right of the view,
// right justify the view or left justify the view
// when the width of the view is smaller than the container.
int maxX = viewSize.width - extentSize.width;
if (scrollable == null || pane.getComponentOrientation().isLeftToRight()) {
if (viewPosition.x > maxX) {
viewPosition.x = Math.max(0, maxX);
}
}
else {
// NOT SUPPORTED YET
viewPosition.x = maxX < 0 ? maxX : Math.max(0, Math.min(maxX, viewPosition.x));
}
// If the new viewport size would leave empty space below the view,
// bottom justify the view or top justify the view
// when the height of the view is smaller than the container.
int maxY = viewSize.height - extentSize.height;
if (viewPosition.y > maxY) {
viewPosition.y = Math.max(0, maxY);
}
// If we haven't been advised about how the viewports size should change wrt to the viewport,
// i.e. if the view isn't an instance of Scrollable, then adjust the views size as follows.
if (scrollable == null) {
// If the origin of the view is showing and the viewport is bigger than the views preferred size,
// then make the view the same size as the viewport.
if (viewPosition.x == 0 && actualSize.width > viewPreferredSize.width) viewSize.width = actualSize.width;
if (viewPosition.y == 0 && actualSize.height > viewPreferredSize.height) viewSize.height = actualSize.height;
}
// do not force viewport size on editor component, e.g. EditorTextField and LanguageConsole
if (!(view instanceof TypingTarget)) {
if (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER == pane.getHorizontalScrollBarPolicy()) {
viewPosition.x = 0;
viewSize.width = actualSize.width;
}
if (ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER == pane.getVerticalScrollBarPolicy()) {
viewPosition.y = 0;
viewSize.height = actualSize.height;
}
}
viewport.setViewPosition(viewPosition);
viewport.setViewSize(viewSize);
}
}
@@ -314,7 +314,8 @@ public final class IdeMouseEventDispatcher {
private static JScrollBar findHorizontalScrollBar(Component c) {
if (c == null) return null;
if (c instanceof JScrollPane) {
return ((JScrollPane)c).getHorizontalScrollBar();
JScrollBar scrollBar = ((JScrollPane)c).getHorizontalScrollBar();
return scrollBar != null && scrollBar.isVisible() ? scrollBar : null;
}
if (isDiagramViewComponent(c)) {
@@ -323,7 +324,7 @@ public final class IdeMouseEventDispatcher {
if (view.getComponent(i) instanceof JScrollBar) {
final JScrollBar scrollBar = (JScrollBar)view.getComponent(i);
if (scrollBar.getOrientation() == Adjustable.HORIZONTAL) {
return scrollBar;
return scrollBar.isVisible() ? scrollBar : null;
}
}
}