Browse Source
【问题原因】 1. 移植JScrollPane的触摸板滚轮交互逻辑到表单布局和报表网格面板中 2. 复用表单和报表的滚轮处理逻辑, 表单和报表各自实现所需的接口即可 【改动思路】 同上research/11.0
Starryi
3 years ago
6 changed files with 480 additions and 28 deletions
@ -0,0 +1,31 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.MouseWheelListener; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/23 |
||||
*/ |
||||
public class DesignerScaleMouseWheelHandler implements MouseWheelListener { |
||||
private final ScalePane scalePane; |
||||
private final int step; |
||||
|
||||
public DesignerScaleMouseWheelHandler(ScalePane scalePane, int step) { |
||||
this.scalePane = scalePane; |
||||
this.step = step; |
||||
} |
||||
|
||||
@Override |
||||
public void mouseWheelMoved(MouseWheelEvent e) { |
||||
int dir = e.getWheelRotation(); |
||||
JFormSliderPane slidePane = this.scalePane.getSlidePane(); |
||||
int old_resolution = slidePane.getShowValue(); |
||||
slidePane.setShowValue(old_resolution - (dir * step)); |
||||
} |
||||
|
||||
public interface ScalePane { |
||||
JFormSliderPane getSlidePane(); |
||||
} |
||||
} |
@ -0,0 +1,279 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import javax.swing.JScrollBar; |
||||
import javax.swing.JViewport; |
||||
import javax.swing.Scrollable; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.Component; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.MouseWheelListener; |
||||
|
||||
/** |
||||
* 实现设计器面板的触摸板滚动移动交互 https://work.fineres.com/browse/REPORT-55989
|
||||
* |
||||
* mouseWheelMoved 的具体实现来自 |
||||
* @link {javax.swing.plaf.basic.BasicScrollPaneUI.Handler#mouseWheelMoved} |
||||
* scrollByUnits 的具体实现来自 |
||||
* @link {javax.swing.plaf.basic.BasicScrollPaneUI#scrollByUnits} |
||||
* scrollByBlock 的具体实现来自 |
||||
* @link {javax.swing.plaf.basic.BasicScrollPaneUI#scrollByBlock} |
||||
*/ |
||||
public class DesignerTranslateMouseWheelHandler implements MouseWheelListener { |
||||
private final ScrollPane scrollpane; |
||||
|
||||
public DesignerTranslateMouseWheelHandler(ScrollPane scrollpane) { |
||||
this.scrollpane = scrollpane; |
||||
} |
||||
|
||||
@Override |
||||
public void mouseWheelMoved(MouseWheelEvent e) { |
||||
if (scrollpane.isWheelScrollingEnabled() && |
||||
e.getWheelRotation() != 0) { |
||||
JScrollBar toScroll = scrollpane.getVerticalScrollBar(); |
||||
int direction = e.getWheelRotation() < 0 ? -1 : 1; |
||||
int orientation = SwingConstants.VERTICAL; |
||||
|
||||
// find which scrollbar to scroll, or return if none
|
||||
if (toScroll == null || !toScroll.isVisible() |
||||
|| e.isShiftDown()) { |
||||
toScroll = scrollpane.getHorizontalScrollBar(); |
||||
if (toScroll == null || !toScroll.isVisible()) { |
||||
return; |
||||
} |
||||
orientation = SwingConstants.HORIZONTAL; |
||||
} |
||||
|
||||
e.consume(); |
||||
|
||||
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { |
||||
JViewport vp = scrollpane.getViewport(); |
||||
if (vp == null) { return; } |
||||
Component comp = vp.getView(); |
||||
int units = Math.abs(e.getUnitsToScroll()); |
||||
|
||||
// When the scrolling speed is set to maximum, it's possible
|
||||
// for a single wheel click to scroll by more units than
|
||||
// will fit in the visible area. This makes it
|
||||
// hard/impossible to get to certain parts of the scrolling
|
||||
// Component with the wheel. To make for more accurate
|
||||
// low-speed scrolling, we limit scrolling to the block
|
||||
// increment if the wheel was only rotated one click.
|
||||
boolean limitScroll = Math.abs(e.getWheelRotation()) == 1; |
||||
|
||||
// Check if we should use the visibleRect trick
|
||||
Object fastWheelScroll = toScroll.getClientProperty( |
||||
"JScrollBar.fastWheelScrolling"); |
||||
if (Boolean.TRUE == fastWheelScroll && |
||||
comp instanceof Scrollable) { |
||||
// 5078454: Under maximum acceleration, we may scroll
|
||||
// by many 100s of units in ~1 second.
|
||||
//
|
||||
// BasicScrollBarUI.scrollByUnits() can bog down the EDT
|
||||
// with repaints in this situation. However, the
|
||||
// Scrollable interface allows us to pass in an
|
||||
// arbitrary visibleRect. This allows us to accurately
|
||||
// calculate the total scroll amount, and then update
|
||||
// the GUI once. This technique provides much faster
|
||||
// accelerated wheel scrolling.
|
||||
Scrollable scrollComp = (Scrollable) comp; |
||||
Rectangle viewRect = vp.getViewRect(); |
||||
int startingX = viewRect.x; |
||||
boolean leftToRight = |
||||
comp.getComponentOrientation().isLeftToRight(); |
||||
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); |
||||
} |
||||
} |
||||
|
||||
for (int i = 0; i < units; i++) { |
||||
int unitIncr = |
||||
scrollComp.getScrollableUnitIncrement(viewRect, |
||||
orientation, direction); |
||||
// Modify the visible rect for the next unit, and
|
||||
// check to see if we're at the end already.
|
||||
if (orientation == SwingConstants.VERTICAL) { |
||||
if (direction < 0) { |
||||
viewRect.y -= unitIncr; |
||||
if (viewRect.y <= scrollMin) { |
||||
viewRect.y = scrollMin; |
||||
break; |
||||
} |
||||
} |
||||
else { // (direction > 0
|
||||
viewRect.y += unitIncr; |
||||
if (viewRect.y >= scrollMax) { |
||||
viewRect.y = scrollMax; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
// Scroll left
|
||||
if ((leftToRight && direction < 0) || |
||||
(!leftToRight && direction > 0)) { |
||||
viewRect.x -= unitIncr; |
||||
if (leftToRight) { |
||||
if (viewRect.x < scrollMin) { |
||||
viewRect.x = scrollMin; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
// Scroll right
|
||||
else if ((leftToRight && direction > 0) || |
||||
(!leftToRight && direction < 0)) { |
||||
viewRect.x += unitIncr; |
||||
if (leftToRight) { |
||||
if (viewRect.x > scrollMax) { |
||||
viewRect.x = scrollMax; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
assert false : "Non-sensical ComponentOrientation / scroll direction"; |
||||
} |
||||
} |
||||
} |
||||
// Set the final view position on the ScrollBar
|
||||
if (orientation == SwingConstants.VERTICAL) { |
||||
toScroll.setValue(viewRect.y); |
||||
} |
||||
else { |
||||
if (leftToRight) { |
||||
toScroll.setValue(viewRect.x); |
||||
} |
||||
else { |
||||
// rightToLeft scrollbars are oriented with
|
||||
// minValue on the right and maxValue on the
|
||||
// left.
|
||||
int newPos = toScroll.getValue() - |
||||
(viewRect.x - startingX); |
||||
if (newPos < scrollMin) { |
||||
newPos = scrollMin; |
||||
} |
||||
else if (newPos > scrollMax) { |
||||
newPos = scrollMax; |
||||
} |
||||
toScroll.setValue(newPos); |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
// Viewport's view is not a Scrollable, or fast wheel
|
||||
// scrolling is not enabled.
|
||||
scrollByUnits(toScroll, direction, |
||||
units, limitScroll); |
||||
} |
||||
} |
||||
else if (e.getScrollType() == |
||||
MouseWheelEvent.WHEEL_BLOCK_SCROLL) { |
||||
scrollByBlock(toScroll, direction); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Method for scrolling by a unit increment. |
||||
* Added for mouse wheel scrolling support, RFE 4202656. |
||||
* |
||||
* If limitByBlock is set to true, the scrollbar will scroll at least 1 |
||||
* unit increment, but will not scroll farther than the block increment. |
||||
* See BasicScrollPaneUI.Handler.mouseWheelMoved(). |
||||
*/ |
||||
static void scrollByUnits(JScrollBar scrollbar, int direction, |
||||
int units, boolean limitToBlock) { |
||||
// This method is called from BasicScrollPaneUI to implement wheel
|
||||
// scrolling, as well as from scrollByUnit().
|
||||
int delta; |
||||
int limit = -1; |
||||
|
||||
if (limitToBlock) { |
||||
if (direction < 0) { |
||||
limit = scrollbar.getValue() - |
||||
scrollbar.getBlockIncrement(direction); |
||||
} |
||||
else { |
||||
limit = scrollbar.getValue() + |
||||
scrollbar.getBlockIncrement(direction); |
||||
} |
||||
} |
||||
|
||||
for (int i=0; i<units; i++) { |
||||
if (direction > 0) { |
||||
delta = scrollbar.getUnitIncrement(direction); |
||||
} |
||||
else { |
||||
delta = -scrollbar.getUnitIncrement(direction); |
||||
} |
||||
|
||||
int oldValue = scrollbar.getValue(); |
||||
int newValue = oldValue + delta; |
||||
|
||||
// Check for overflow.
|
||||
if (delta > 0 && newValue < oldValue) { |
||||
newValue = scrollbar.getMaximum(); |
||||
} |
||||
else if (delta < 0 && newValue > oldValue) { |
||||
newValue = scrollbar.getMinimum(); |
||||
} |
||||
if (oldValue == newValue) { |
||||
break; |
||||
} |
||||
|
||||
if (limitToBlock && i > 0) { |
||||
assert limit != -1; |
||||
if ((direction < 0 && newValue < limit) || |
||||
(direction > 0 && newValue > limit)) { |
||||
break; |
||||
} |
||||
} |
||||
scrollbar.setValue(newValue); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Method for scrolling by a block increment. |
||||
* Added for mouse wheel scrolling support, RFE 4202656. |
||||
*/ |
||||
static void scrollByBlock(JScrollBar scrollbar, int direction) { |
||||
// This method is called from BasicScrollPaneUI to implement wheel
|
||||
// scrolling, and also from scrollByBlock().
|
||||
int oldValue = scrollbar.getValue(); |
||||
int blockIncrement = scrollbar.getBlockIncrement(direction); |
||||
int delta = blockIncrement * ((direction > 0) ? +1 : -1); |
||||
int newValue = oldValue + delta; |
||||
|
||||
// Check for overflow.
|
||||
if (delta > 0 && newValue < oldValue) { |
||||
newValue = scrollbar.getMaximum(); |
||||
} |
||||
else if (delta < 0 && newValue > oldValue) { |
||||
newValue = scrollbar.getMinimum(); |
||||
} |
||||
|
||||
scrollbar.setValue(newValue); |
||||
} |
||||
|
||||
public interface ScrollPane { |
||||
boolean isWheelScrollingEnabled(); |
||||
JScrollBar getVerticalScrollBar(); |
||||
JScrollBar getHorizontalScrollBar(); |
||||
JViewport getViewport(); |
||||
} |
||||
} |
@ -0,0 +1,75 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.common.inputevent.InputEventBaseOnOS; |
||||
|
||||
import javax.swing.JScrollBar; |
||||
import javax.swing.JViewport; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.MouseWheelListener; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/24 |
||||
*/ |
||||
public class FormAreaMouseWheelHandler implements MouseWheelListener { |
||||
private final DesignerTranslateMouseWheelHandler translateMouseWheelHandler; |
||||
private final DesignerScaleMouseWheelHandler scaleMouseWheelHandler; |
||||
|
||||
public FormAreaMouseWheelHandler(FormArea formArea) { |
||||
translateMouseWheelHandler = new DesignerTranslateMouseWheelHandler(new FormAreaScrollPaneAdapter(formArea)); |
||||
scaleMouseWheelHandler = new DesignerScaleMouseWheelHandler(new FormAreaScalePaneAdapter(formArea), FormArea.SHOWVALMIN); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseWheelMoved(MouseWheelEvent e) { |
||||
if (InputEventBaseOnOS.isControlDown(e)) { |
||||
scaleMouseWheelHandler.mouseWheelMoved(e); |
||||
} else { |
||||
translateMouseWheelHandler.mouseWheelMoved(e); |
||||
} |
||||
} |
||||
|
||||
private static class FormAreaScalePaneAdapter implements DesignerScaleMouseWheelHandler.ScalePane { |
||||
private final FormArea formArea; |
||||
|
||||
public FormAreaScalePaneAdapter(FormArea formArea) { |
||||
this.formArea = formArea; |
||||
} |
||||
|
||||
@Override |
||||
public JFormSliderPane getSlidePane() { |
||||
return formArea.getSlidePane(); |
||||
} |
||||
} |
||||
|
||||
private static class FormAreaScrollPaneAdapter implements DesignerTranslateMouseWheelHandler.ScrollPane { |
||||
private final FormArea formArea; |
||||
private final JViewport viewport; |
||||
|
||||
public FormAreaScrollPaneAdapter(FormArea formArea) { |
||||
this.formArea = formArea; |
||||
this.viewport = new JViewport(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isWheelScrollingEnabled() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public JScrollBar getVerticalScrollBar() { |
||||
return formArea.getVerticalScrollBar(); |
||||
} |
||||
|
||||
@Override |
||||
public JScrollBar getHorizontalScrollBar() { |
||||
return formArea.getHorizontalScrollBar(); |
||||
} |
||||
|
||||
@Override |
||||
public JViewport getViewport() { |
||||
return this.viewport; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,75 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.common.inputevent.InputEventBaseOnOS; |
||||
|
||||
import javax.swing.JScrollBar; |
||||
import javax.swing.JViewport; |
||||
import java.awt.event.MouseWheelEvent; |
||||
import java.awt.event.MouseWheelListener; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/24 |
||||
*/ |
||||
public class ReportComponentCompositeMouseWheelHandler implements MouseWheelListener { |
||||
private final DesignerTranslateMouseWheelHandler translateMouseWheelHandler; |
||||
private final DesignerScaleMouseWheelHandler scaleMouseWheelHandler; |
||||
|
||||
public ReportComponentCompositeMouseWheelHandler(ReportComponentComposite componentComposite) { |
||||
translateMouseWheelHandler = new DesignerTranslateMouseWheelHandler(new ScrollPaneAdapter(componentComposite)); |
||||
scaleMouseWheelHandler = new DesignerScaleMouseWheelHandler(new ScalePaneAdapter(componentComposite), ReportComponentComposite.DIR); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseWheelMoved(MouseWheelEvent e) { |
||||
if (InputEventBaseOnOS.isControlDown(e)) { |
||||
scaleMouseWheelHandler.mouseWheelMoved(e); |
||||
} else { |
||||
translateMouseWheelHandler.mouseWheelMoved(e); |
||||
} |
||||
} |
||||
|
||||
private static class ScrollPaneAdapter implements DesignerTranslateMouseWheelHandler.ScrollPane { |
||||
private final ReportComponentComposite componentComposite; |
||||
private JViewport viewport; |
||||
|
||||
public ScrollPaneAdapter(ReportComponentComposite componentComposite) { |
||||
this.componentComposite = componentComposite; |
||||
this.viewport = new JViewport(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isWheelScrollingEnabled() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public JScrollBar getVerticalScrollBar() { |
||||
return componentComposite.getEditingReportComponent().getVerticalScrollBar(); |
||||
} |
||||
|
||||
@Override |
||||
public JScrollBar getHorizontalScrollBar() { |
||||
return componentComposite.getEditingReportComponent().getHorizontalScrollBar(); |
||||
} |
||||
|
||||
@Override |
||||
public JViewport getViewport() { |
||||
return viewport; |
||||
} |
||||
} |
||||
|
||||
private static class ScalePaneAdapter implements DesignerScaleMouseWheelHandler.ScalePane { |
||||
private final ReportComponentComposite componentComposite; |
||||
|
||||
public ScalePaneAdapter(ReportComponentComposite componentComposite) { |
||||
this.componentComposite = componentComposite; |
||||
} |
||||
|
||||
@Override |
||||
public JFormSliderPane getSlidePane() { |
||||
return componentComposite.getjSliderContainer(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue