package org.ovirt.engine.ui.webadmin.section.main.view.popup.host; import java.util.logging.Logger; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.ScrollPanel; /* * Condition 1: The _nicList_ panel has a total height < the height of the scroll panel * Action 1: Do nothing during a drag over * * Condition 2: The _nicList_ panel has a total height > the height of the scroll panel (> 6 nics) * Action 2: Enable auto-scroll regions at the bottom and top of the scroll panel: * * - If drag pointer hovers over the upper auto-scroll region for >100ms?, and there * is _nicList_ content above the viewport, scroll up to see the above content * * - If drag pointer hovers over the lower auto-scroll region for >100ms?, and there * is _nicList_ content below the viewport, scroll down to see the lower content. * * - If the drag pointer hovers over the upper or lower auto-scroll region for <100ms, * just display its existence but don't scroll. */ public class AutoScrollAdapter implements AutoScrollEnableEvent.Handler, AutoScrollDisableEvent.Handler, AutoScrollOverEvent.Handler, MouseMoveHandler { public static final int EDGE_DELTA_FOR_SCROLLING = 20; // in pixels public static final int SCROLL_STEP = 20; // in pixels public static final int AUTO_SCROLL_CHECK_INTERVAL = 100; // in milliseconds protected final Logger log = Logger.getLogger(AutoScrollAdapter.class.getName()); protected final ScrollPanel sp; protected final Timer scrollCheck = new Timer() { @Override public void run() { if (!enabled) { scrollCheck.cancel(); return; } int top = sp.getAbsoluteTop(); int height = sp.getOffsetHeight(); int topEdgeDelta = mouseY < top || mouseY > (top+height) ? -1 : mouseY - top; int bottomEdgeDelta = mouseY < top || mouseY > (top+height) ? -1 : top + height - mouseY; if (topEdgeDelta > -1 && topEdgeDelta < EDGE_DELTA_FOR_SCROLLING) { log.finer("inside the EDGE_DELTA_FOR_SCROLLING on the top"); //$NON-NLS-1$ int minPos = sp.getMinimumVerticalScrollPosition(); int currPosition = sp.getVerticalScrollPosition(); if (currPosition > minPos) { int newPosition = Math.max(minPos, currPosition - SCROLL_STEP); sp.setVerticalScrollPosition(newPosition); } } else if (bottomEdgeDelta > -1 && bottomEdgeDelta < EDGE_DELTA_FOR_SCROLLING) { log.finer("inside the EDGE_DELTA_FOR_SCROLLING on the bottom"); //$NON-NLS-1$ int maxPos = sp.getMaximumVerticalScrollPosition(); int currPosition = sp.getVerticalScrollPosition(); if (currPosition < maxPos) { int newPosition = Math.min(maxPos, currPosition + SCROLL_STEP); sp.setVerticalScrollPosition(newPosition); } } } }; protected boolean enabled = false; protected int mouseY = -1; public AutoScrollAdapter(EventBus eventBus, ScrollPanel sp) { log.fine("attaching auto scroll handler to element "); //$NON-NLS-1$ this.sp = sp; AutoScrollEnableEvent.register(eventBus, this); AutoScrollDisableEvent.register(eventBus, this); AutoScrollOverEvent.register(eventBus, this); sp.addBitlessDomHandler(this, MouseMoveEvent.getType()); } @Override public void enableAutoScroll(AutoScrollEnableEvent event) { if (!enabled) { log.finer("auto-scrolling has been enabled"); //$NON-NLS-1$ enabled = true; scrollCheck.scheduleRepeating(AUTO_SCROLL_CHECK_INTERVAL); } } @Override public void disableAutoScroll(AutoScrollDisableEvent event) { if (enabled) { log.finer("auto-scrolling has been disabled"); //$NON-NLS-1$ enabled = false; scrollCheck.cancel(); } } @Override public void onMouseMove(MouseMoveEvent event) { // mouse location normally mouseY = event.getClientY(); } @Override public void overAutoScroll(AutoScrollOverEvent event) { // mouse location during a drag-and-drop mouseY = event.getClientY(); } }