All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.openapi.editor.impl.PreciseMouseWheelScroller Maven / Gradle / Ivy

/*
 * Copyright 2000-2015 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.openapi.editor.impl;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.lang.reflect.Method;

/**
 * Implements precise (with sub-line resolution) mouse wheel/trackpad scrolling in JScrollPane if platform supports it 
 * (currently known to work on Mac OS with Java 7 or later).
 * 

* Scroll pane's view is supposed to implement {@link Scrollable}. * * @see MouseWheelEvent#getPreciseWheelRotation() */ public class PreciseMouseWheelScroller implements MouseWheelListener { private static final Logger LOGGER = Logger.getInstance(PreciseMouseWheelScroller.class); private static Method PRECISE_WHEEL_ROTATION_GETTER; static { if (SystemInfo.isJavaVersionAtLeast("1.7")) { try { Method method = MouseWheelEvent.class.getMethod("getPreciseWheelRotation"); Class returnType = method.getReturnType(); if (!returnType.equals(double.class)) throw new RuntimeException("Unexpected method return type: " + returnType); PRECISE_WHEEL_ROTATION_GETTER = method; } catch (Exception e) { LOGGER.warn("Couldn't access getPreciseWheelRotation method", e); } } } public static void install(@NotNull JScrollPane scrollPane) { scrollPane.setWheelScrollingEnabled(false); scrollPane.addMouseWheelListener(new PreciseMouseWheelScroller(scrollPane)); } private final JScrollPane myScrollPane; private PreciseMouseWheelScroller(JScrollPane scrollPane) { myScrollPane = scrollPane; } @Override public void mouseWheelMoved(MouseWheelEvent e) { e.consume(); if (e.getWheelRotation() != 0) { int orientation = SwingConstants.VERTICAL; JScrollBar toScroll = myScrollPane.getVerticalScrollBar(); if (toScroll == null || !toScroll.isVisible() || e.isShiftDown()) { orientation = SwingConstants.HORIZONTAL; toScroll = myScrollPane.getHorizontalScrollBar(); if (toScroll == null || !toScroll.isVisible()) { return; } } int direction = e.getWheelRotation() < 0 ? -1 : 1; if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { JViewport vp = myScrollPane.getViewport(); Component comp = vp.getView(); boolean limitScroll = Math.abs(e.getWheelRotation()) == 1; Scrollable scrollComp = (Scrollable) comp; Rectangle viewRect = vp.getViewRect(); int scrollMin = toScroll.getMinimum(); int scrollMax = toScroll.getMaximum() - toScroll.getModel().getExtent(); if (limitScroll) { int blockIncr = scrollComp.getScrollableBlockIncrement(viewRect, orientation, direction); if (direction < 0) { scrollMin = Math.max(scrollMin, toScroll.getValue() - blockIncr); } else { scrollMax = Math.min(scrollMax, toScroll.getValue() + blockIncr); } } double units = getUnitsToScroll(e); double shift = scrollComp.getScrollableUnitIncrement(viewRect, orientation, direction) * units; if (orientation == SwingConstants.VERTICAL) { viewRect.y += shift; if (direction < 0) { if (viewRect.y <= scrollMin) { viewRect.y = scrollMin; } } else { if (viewRect.y >= scrollMax) { viewRect.y = scrollMax; } } toScroll.setValue(viewRect.y); } else { viewRect.x += shift; if (direction < 0) { if (viewRect.x < scrollMin) { viewRect.x = scrollMin; } } else { if (viewRect.x > scrollMax) { viewRect.x = scrollMax; } } toScroll.setValue(viewRect.x); } } else if (e.getScrollType() == MouseWheelEvent.WHEEL_BLOCK_SCROLL) { int oldValue = toScroll.getValue(); int blockIncrement = toScroll.getBlockIncrement(direction); int delta = blockIncrement * direction; int newValue = oldValue + delta; if (delta > 0 && newValue < oldValue) { newValue = toScroll.getMaximum(); } else if (delta < 0 && newValue > oldValue) { newValue = toScroll.getMinimum(); } toScroll.setValue(newValue); } } } // Required method was added in Java 7, but we need to compile for Java 6, so we resort to reflection private static double getUnitsToScroll(MouseWheelEvent e) { if (PRECISE_WHEEL_ROTATION_GETTER != null) { try { Double value = (Double)PRECISE_WHEEL_ROTATION_GETTER.invoke(e); return e.getScrollAmount() * value; } catch (Exception ex) { LOGGER.debug("Error calling getPreciseWheelRotation method", ex); } } return e.getUnitsToScroll(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy