diff --git a/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java b/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java index 8065cf6d33..c14fe698fd 100644 --- a/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java +++ b/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java @@ -18,6 +18,7 @@ import javax.swing.JLayer; import javax.swing.ScrollPaneConstants; import javax.swing.UIManager; import javax.swing.JTextArea; +import javax.swing.JScrollBar; import java.awt.Color; import java.awt.Component; import java.awt.Composite; @@ -517,4 +518,88 @@ public class FineUIUtils { DesignerFrame parent = DesignerContext.getDesignerFrame(); return new Dimension((int) (parent.getWidth() * width),(int) (parent.getHeight() * height)); } + + /** + * 处理子面板的滚动事件。 + * 根据滚动情况,判断是否需要将事件传递给父面板,或者由子面板自行处理滚动。 + * + * @param childScrollBar 子面板的滚动条 + * @param parentScrollBar 父面板的滚动条 + * @param scrollAmount 滚动增量,通常是鼠标滚轮的滚动值 + */ + public static void handleChildScrollEvent(JScrollBar childScrollBar, JScrollBar parentScrollBar, int scrollAmount) { + // 如果子面板的滚动条为空,返回 + if (childScrollBar == null) { + return; + } + // 如果子面板没有显示滚动条,直接将滚动事件传递给父面板 + if (!childScrollBar.isVisible()) { + propagateScrollToParent(parentScrollBar, scrollAmount); + return; + } + // 获取子面板当前的滚动值、最小值、最大值和可见区域的高度 + int currentScrollValue = childScrollBar.getValue(); + int minScrollValue = childScrollBar.getMinimum(); + int maxScrollValue = childScrollBar.getMaximum(); + int visibleAreaHeight = childScrollBar.getVisibleAmount(); + // 如果滚动到顶部或到底部,将事件传递给父面板 + if (isScrolledToTop(currentScrollValue, minScrollValue, scrollAmount) + || isScrolledToBottom(currentScrollValue, maxScrollValue, visibleAreaHeight, scrollAmount)) { + propagateScrollToParent(parentScrollBar, scrollAmount); + } else { + // 否则由子面板自己处理滚动更新滚动值 + childScrollBar.setValue(currentScrollValue + calculateScrollIncrement(childScrollBar, scrollAmount)); + } + } + + /** + * 判断是否滚动到顶部。 + * + * @param currentScrollValue 当前滚动条的位置 + * @param minScrollValue 滚动条的最小值 + * @param scrollAmount 滚动增量 + * @return 如果滚动到顶部,返回 true;否则返回 false + */ + private static boolean isScrolledToTop(int currentScrollValue, int minScrollValue, int scrollAmount) { + return scrollAmount < 0 && currentScrollValue == minScrollValue; + } + + /** + * 判断是否滚动到底部。 + * + * @param currentScrollValue 当前滚动条的位置 + * @param maxScrollValue 滚动条的最大值 + * @param visibleAreaHeight 可见区域的高度 + * @param scrollAmount 滚动增量 + * @return 如果滚动到底部,返回 true;否则返回 false + */ + private static boolean isScrolledToBottom(int currentScrollValue, int maxScrollValue, int visibleAreaHeight, int scrollAmount) { + return scrollAmount > 0 && currentScrollValue == maxScrollValue - visibleAreaHeight; + } + + /** + * 将滚动事件传递给父面板,处理父面板的滚动。 + * + * @param parentScrollBar 父面板的滚动条 + * @param scrollAmount 滚动增量 + */ + private static void propagateScrollToParent(JScrollBar parentScrollBar, int scrollAmount) { + if (parentScrollBar != null) { + // 根据滚动增量计算并更新父面板滚动条的位置 + int scrollIncrement = calculateScrollIncrement(parentScrollBar, scrollAmount); + parentScrollBar.setValue(parentScrollBar.getValue() + scrollIncrement); + } + } + + /** + * 计算滚动增量,基于滚动条的单位增量和滚动的数量,UIScrollPane中设置的30 + * + * @param scrollBar 滚动条 + * @param scrollAmount 滚动增量 + * @return 计算出的增量值 + */ + private static int calculateScrollIncrement(JScrollBar scrollBar, int scrollAmount) { + // 获取滚动条的单位增量,并计算实际的滚动增量 + return scrollAmount * scrollBar.getUnitIncrement(1); + } } diff --git a/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java b/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java index 812b7352f3..aca6e19780 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java @@ -49,6 +49,7 @@ public class EventPane extends BasicPane { private EditAction editAction; private RemoveAction removeAction; private String[] eventName; + private UIScrollPane scrollPane; private int itemHeight = 20; @@ -76,12 +77,22 @@ public class EventPane extends BasicPane { eventList.setCellRenderer(render); eventList.addMouseListener(editListener); eventList.setBackground(FlatUIUtils.getUIColor("fill.normal", Color.WHITE)); - JScrollPane scrollPane = new UIScrollPane(eventList); + scrollPane = new UIScrollPane(eventList); scrollPane.setBorder(new FineRoundBorder()); //让事件设置列表铺满,有特殊设置在外层调用处修改 this.add(column(LayoutConstants.VGAP_SMALL, cell(toolBar), cell(scrollPane).weight(1)).getComponent()); } + /** + * 获取当前面板的滚动面板(UIScrollPane)。 + * 用于获取滚动条或进行其他基于滚动面板的操作。 + * + * @return 当前组件的 UIScrollPane 实例 + */ + public UIScrollPane getScrollPane() { + return scrollPane; + } + @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); diff --git a/designer-realize/src/main/java/com/fr/design/webattr/ToolBarDragPane.java b/designer-realize/src/main/java/com/fr/design/webattr/ToolBarDragPane.java index 66ccb8cd61..e7555a09eb 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/ToolBarDragPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/ToolBarDragPane.java @@ -11,6 +11,7 @@ import com.fr.design.constants.LayoutConstants; import com.fr.design.gui.core.WidgetOption; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.utils.gui.GUICoreUtils; @@ -29,7 +30,6 @@ import java.awt.image.ImageObserver; import javax.swing.Icon; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; @@ -61,6 +61,7 @@ public class ToolBarDragPane extends WidgetToolBarPane { private JTable layoutTable; private UICheckBox isUseToolBarCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Use_ToolBar")); // 是否使用工具栏 private boolean isEnabled; + private UIScrollPane scrollPane; /** * 工具栏Pane @@ -191,15 +192,26 @@ public class ToolBarDragPane extends WidgetToolBarPane { //工具栏面板center布局:顶部工具栏-上移动按钮-图标面板-下移动按钮-底部工具栏 JPanel movePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + scrollPane = new UIScrollPane(buttonTablePanel); movePane.add(column(1, cell(topToolbarPanel), cell(topButton), - cell(buttonTablePanel), + cell(scrollPane), cell(downButton), cell(bottomToolbarPanel) ).getComponent()); //工具栏整体面板 - this.add(column(LayoutConstants.VERTICAL_GAP, cell(northPanel), cell(new JScrollPane(movePane))).getComponent()); + this.add(column(LayoutConstants.VERTICAL_GAP, cell(northPanel), cell(movePane)).getComponent()); + } + + /** + * 获取当前面板的滚动面板(UIScrollPane)。 + * 用于获取滚动条或进行其他基于滚动面板的操作。 + * + * @return 当前组件的 UIScrollPane 实例 + */ + public UIScrollPane getScrollPane() { + return scrollPane; } /** diff --git a/designer-realize/src/main/java/com/fr/design/webattr/WebSettingPane.java b/designer-realize/src/main/java/com/fr/design/webattr/WebSettingPane.java index c39aa988c4..426e0085f6 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/WebSettingPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/WebSettingPane.java @@ -1,6 +1,7 @@ package com.fr.design.webattr; import com.fine.theme.utils.FineUIScale; +import com.fine.theme.utils.FineUIUtils; import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.design.beans.BasicBeanPane; import com.fr.design.border.FineBorderFactory; @@ -62,6 +63,7 @@ public abstract class WebSettingPane extends BasicBeanPane //事件设置 JPanel eventPanel = new JPanel(new BorderLayout()); eventPane = new EventPane(getEventNames()); + eventPane.setPreferredSize(new Dimension(super.getPreferredSize().width, FineUIScale.scale(180))); UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Event_Set")); wrapBoldLabelWithUnderline(label); eventPanel.add(column(LayoutConstants.VGAP_SMALL, cell(label), cell(eventPane)).getComponent()); @@ -94,7 +96,13 @@ public abstract class WebSettingPane extends BasicBeanPane ).getComponent()); } this.setLayout(new BorderLayout()); - this.add(new UIScrollPane(panel)); + UIScrollPane parentScrollPane = new UIScrollPane(panel); + this.add(parentScrollPane); + // 存在子区域也是滚动面板,需要处理滚动事件传递给父面板 + UIScrollPane buttonTablePane = dragToolBarPane.getScrollPane(); + buttonTablePane.addMouseWheelListener(e -> FineUIUtils.handleChildScrollEvent(buttonTablePane.getVerticalScrollBar(), parentScrollPane.getVerticalScrollBar(), e.getWheelRotation())); + UIScrollPane eventList = eventPane.getScrollPane(); + eventList.addMouseWheelListener(e -> FineUIUtils.handleChildScrollEvent(eventList.getVerticalScrollBar(), parentScrollPane.getVerticalScrollBar(), e.getWheelRotation())); } ItemListener itemListener = new ItemListener() {