diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java index d85989b4e718..132984f06b27 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java @@ -18,7 +18,6 @@ package com.intellij.ui.components; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.IdeGlassPane.TopComponent; -import com.intellij.ui.ComponentSettings; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.RegionPainter; import com.intellij.util.ui.UIUtil; @@ -34,8 +33,6 @@ import java.awt.Font; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; -import static com.intellij.util.SystemProperties.isTrueSmoothScrollingEnabled; - /** * Our implementation of a scroll bar with the custom UI. * Also it provides a method to create custom UI for our custom L&Fs. @@ -67,7 +64,7 @@ public class JBScrollBar extends JScrollBar implements TopComponent, Interpolabl public JBScrollBar(@JdkConstants.AdjustableOrientation int orientation, int value, int extent, int min, int max) { super(orientation, value, extent, min, max); - if (isTrueSmoothScrollingEnabled()) setModel(new Model(value, extent, min, max)); + setModel(new Model(value, extent, min, max)); putClientProperty("JScrollBar.fastWheelScrolling", Boolean.TRUE); // fast scrolling for JDK 6 } @@ -164,11 +161,8 @@ public class JBScrollBar extends JScrollBar implements TopComponent, Interpolabl if (parent instanceof JBScrollPane) { JBScrollPane pane = (JBScrollPane)parent; JViewport viewport = pane.getViewport(); - if (viewport != null) { - ComponentSettings settings = ComponentSettings.getInstance(); - if (settings.isTrueSmoothScrollingEligibleFor(viewport.getView()) && settings.isInterpolationEligibleFor(this)) { - delay = pane.getInitialDelay(getValueIsAdjusting()); - } + if (viewport != null && ScrollSettings.isEligibleFor(viewport.getView()) && ScrollSettings.isInterpolationEligibleFor(this)) { + delay = pane.getInitialDelay(getValueIsAdjusting()); } } if (delay > 0) { @@ -204,9 +198,7 @@ public class JBScrollBar extends JScrollBar implements TopComponent, Interpolabl public boolean handleMouseWheelEvent(MouseWheelEvent event) { if (MouseWheelEvent.WHEEL_UNIT_SCROLL != event.getScrollType()) return false; if (event.isShiftDown() == (orientation == VERTICAL)) return false; - - ComponentSettings settings = ComponentSettings.getInstance(); - if (!settings.isTrueSmoothScrollingEligibleFor(this)) return false; + if (!ScrollSettings.isEligibleFor(this)) return false; double delta = getPreciseDelta(event); if (!Double.isFinite(delta)) return false; @@ -250,8 +242,7 @@ public class JBScrollBar extends JScrollBar implements TopComponent, Interpolabl */ private double getPreciseDelta(MouseWheelEvent event) { double rotation = event.getPreciseWheelRotation(); - ComponentSettings settings = ComponentSettings.getInstance(); - if (settings.isPixelPerfectScrollingEnabled()) { + if (ScrollSettings.isPixelPerfectEnabled()) { // calculate an absolute delta if possible if (SystemInfo.isMac) { // Native code in our JDK for Mac uses 0.1 to convert pixels to units, @@ -263,7 +254,7 @@ public class JBScrollBar extends JScrollBar implements TopComponent, Interpolabl int size = font == null ? JBUI.scale(10) : font.getSize(); // assume an unit size return size * rotation * event.getScrollAmount(); } - if (settings.isHighPrecisionScrollingEnabled()) { + if (ScrollSettings.isHighPrecisionEnabled()) { // calculate a relative delta if possible int direction = rotation < 0 ? -1 : 1; int unitIncrement = getUnitIncrement(direction); diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index 70eeb8b6c8a2..459414c10291 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -19,7 +19,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; -import com.intellij.ui.ComponentSettings; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionUtil; @@ -277,7 +276,7 @@ public class JBScrollPane extends JScrollPane { @Override protected void processMouseWheelEvent(MouseWheelEvent e) { - boolean hasAbsoluteDelta = ComponentSettings.getInstance().isPixelPerfectScrollingEnabled(); + boolean hasAbsoluteDelta = ScrollSettings.isPixelPerfectEnabled(); myScrollSource = hasAbsoluteDelta ? ScrollSource.TOUCHPAD : ScrollSource.MOUSE_WHEEL; myWheelRotation = e.getPreciseWheelRotation(); super.processMouseWheelEvent(e); @@ -730,14 +729,9 @@ public class JBScrollPane extends JScrollPane { if (event.isConsumed()) return false; // any rotation expected (forward or backward) boolean ignore = event.getWheelRotation() == 0; - if (ignore) { - ComponentSettings settings = ComponentSettings.getInstance(); - if (settings.isSmoothScrollingSupported()) { - if (settings.isPixelPerfectScrollingEnabled() || settings.isHighPrecisionScrollingEnabled()) { - double rotation = event.getPreciseWheelRotation(); - ignore = rotation == 0.0D || !Double.isFinite(rotation); - } - } + if (ignore && (ScrollSettings.isPixelPerfectEnabled() || ScrollSettings.isHighPrecisionEnabled())) { + double rotation = event.getPreciseWheelRotation(); + ignore = rotation == 0.0D || !Double.isFinite(rotation); } return !ignore && 0 == (SCROLL_MODIFIERS & event.getModifiers()); } diff --git a/platform/platform-api/src/com/intellij/ui/components/ScrollSettings.java b/platform/platform-api/src/com/intellij/ui/components/ScrollSettings.java new file mode 100644 index 000000000000..41081e6b673a --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/ScrollSettings.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2017 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.ui.components; + +import com.intellij.ide.PowerSaveMode; +import com.intellij.ide.RemoteDesktopService; +import com.intellij.ide.ui.UISettings; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.registry.RegistryValue; + +import javax.swing.JDialog; +import javax.swing.JScrollBar; +import javax.swing.RootPaneContainer; +import java.awt.Component; +import java.awt.Container; +import java.awt.Window; + +import static com.intellij.openapi.application.ApplicationManager.getApplication; + +/** + * @author Sergey.Malenkov + */ +final class ScrollSettings { + private static final RegistryValue PIXEL_PERFECT_SCROLLING = Registry.get("idea.true.smooth.scrolling.pixel.perfect"); + private static final RegistryValue HIGH_PRECISION_SCROLLING = Registry.get("idea.true.smooth.scrolling.high.precision"); + + static boolean isEligibleFor(Component component) { + if (component == null || !component.isShowing()) return false; + + Application application = getApplication(); + if (application == null || application.isUnitTestMode()) return false; + if (PowerSaveMode.isEnabled()) return false; + if (RemoteDesktopService.isRemoteSession()) return false; + + UISettings settings = UISettings.getInstanceOrNull(); + return settings != null && settings.getSmoothScrolling(); + } + + static boolean isHighPrecisionEnabled() { + return HIGH_PRECISION_SCROLLING.asBoolean(); + } + + static boolean isPixelPerfectEnabled() { + return PIXEL_PERFECT_SCROLLING.asBoolean(); + } + + /* A heuristics that disables scrolling interpolation in diff / merge windows. + We need to to make scrolling synchronization compatible with the interpolation first. + + NOTE: The implementation is a temporary, ad-hoc heuristics that is needed solely to + facilitate testing of the experimental "true smooth scrolling" feature. */ + static boolean isInterpolationEligibleFor(JScrollBar scrollbar) { + Window window = (Window)scrollbar.getTopLevelAncestor(); + + if (window instanceof JDialog && "Commit Changes".equals(((JDialog)window).getTitle())) { + return false; + } + + if (!(window instanceof RootPaneContainer)) { + return true; + } + + Component[] components = ((RootPaneContainer)window).getContentPane().getComponents(); + + if (components.length == 1 && components[0].getClass().getName().contains("DiffWindow")) { + return false; + } + + if (components.length == 2 && components[0] instanceof Container) { + Component[] subComponents = ((Container)components[0]).getComponents(); + if (subComponents.length == 1) { + String name = subComponents[0].getClass().getName(); + if (name.contains("DiffWindow") || name.contains("MergeWindow")) { + return false; + } + } + } + + return true; + } +}