You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
809 lines
32 KiB
809 lines
32 KiB
package com.fr.design.mainframe; |
|
|
|
import com.fr.base.BaseUtils; |
|
import com.fr.base.vcs.DesignerMode; |
|
import com.fr.common.inputevent.InputEventBaseOnOS; |
|
import com.fr.design.designer.beans.AdapterBus; |
|
import com.fr.design.designer.beans.ComponentAdapter; |
|
import com.fr.design.designer.beans.events.DesignerEditor; |
|
import com.fr.design.designer.beans.events.DesignerEvent; |
|
import com.fr.design.designer.beans.location.Direction; |
|
import com.fr.design.designer.beans.location.Location; |
|
import com.fr.design.designer.beans.models.SelectionModel; |
|
import com.fr.design.designer.beans.models.StateModel; |
|
import com.fr.design.designer.creator.XBorderStyleWidgetCreator; |
|
import com.fr.design.designer.creator.XChartEditor; |
|
import com.fr.design.designer.creator.XCreator; |
|
import com.fr.design.designer.creator.XCreatorUtils; |
|
import com.fr.design.designer.creator.XEditorHolder; |
|
import com.fr.design.designer.creator.XElementCase; |
|
import com.fr.design.designer.creator.XLayoutContainer; |
|
import com.fr.design.designer.creator.XWAbsoluteLayout; |
|
import com.fr.design.designer.creator.XWFitLayout; |
|
import com.fr.design.designer.creator.XWTitleLayout; |
|
import com.fr.design.designer.creator.cardlayout.XCardAddButton; |
|
import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; |
|
import com.fr.design.designer.creator.cardlayout.XWCardLayout; |
|
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; |
|
import com.fr.design.form.util.XCreatorConstants; |
|
import com.fr.design.gui.ibutton.UIButton; |
|
import com.fr.design.gui.imenu.UIPopupMenu; |
|
import com.fr.design.gui.xpane.ToolTipEditor; |
|
import com.fr.design.icon.IconPathConstants; |
|
import com.fr.design.utils.ComponentUtils; |
|
import com.fr.design.utils.gui.GUICoreUtils; |
|
import com.fr.design.utils.gui.LayoutUtils; |
|
import com.fr.general.ComparatorUtils; |
|
import com.fr.stable.Constants; |
|
|
|
import java.util.LinkedList; |
|
import javax.swing.BorderFactory; |
|
import javax.swing.JComponent; |
|
import javax.swing.JPopupMenu; |
|
import javax.swing.JWindow; |
|
import javax.swing.SwingUtilities; |
|
import javax.swing.event.MouseInputAdapter; |
|
import java.awt.Color; |
|
import java.awt.Container; |
|
import java.awt.Cursor; |
|
import java.awt.Insets; |
|
import java.awt.Rectangle; |
|
import java.awt.event.MouseEvent; |
|
|
|
/** |
|
* 普通模式下的鼠标点击、位置处理器 |
|
*/ |
|
public class EditingMouseListener extends MouseInputAdapter { |
|
|
|
private FormDesigner designer; |
|
|
|
/** |
|
* 普通模式下对应的model |
|
*/ |
|
private StateModel stateModel; |
|
|
|
|
|
private XLayoutContainer xTopLayoutContainer; |
|
private XLayoutContainer clickTopLayout; |
|
|
|
/** |
|
* 获取表单设计器 |
|
* |
|
* @return 表单设计器 |
|
*/ |
|
public FormDesigner getDesigner() { |
|
return designer; |
|
} |
|
|
|
/** |
|
* 选择模型,存储当前选择的组件和剪切板 |
|
*/ |
|
private SelectionModel selectionModel; |
|
|
|
/** |
|
* 获取选择模型 |
|
* |
|
* @return 选择 |
|
*/ |
|
public SelectionModel getSelectionModel() { |
|
return selectionModel; |
|
} |
|
|
|
private XCreator lastXCreator; |
|
private MouseEvent lastPressEvent; |
|
private DesignerEditor<? extends JComponent> currentEditor; |
|
private XCreator currentXCreator; |
|
|
|
//备份开始拖动的位置和大小 |
|
private Rectangle dragBackupBounds; |
|
|
|
private int pressX; |
|
private int pressY; |
|
|
|
/** |
|
* 获取最小移动距离 |
|
* |
|
* @return 最小移动距离 |
|
*/ |
|
public int getMinMoveSize() { |
|
return minMoveSize; |
|
} |
|
|
|
private int minDragSize = 5; |
|
private int minMoveSize = 8; |
|
|
|
private static final Insets DEEFAULT_INSETS = new Insets(0,0,0,0); |
|
|
|
//报表块的编辑按钮不灵敏,范围扩大一点 |
|
private static final int GAP = 5; |
|
|
|
private XElementCase xElementCase; |
|
private XChartEditor xChartEditor; |
|
|
|
private JWindow promptWindow = new JWindow(); |
|
|
|
public EditingMouseListener(FormDesigner designer) { |
|
this.designer = designer; |
|
stateModel = designer.getStateModel(); |
|
selectionModel = designer.getSelectionModel(); |
|
UIButton promptButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); |
|
this.promptWindow.add(promptButton); |
|
} |
|
|
|
private void promptUser(int x, int y, XLayoutContainer container) { |
|
if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { |
|
promptWidgetForbidEnter(x, y, container); |
|
} else { |
|
cancelPromptWidgetForbidEnter(); |
|
} |
|
} |
|
|
|
private void promptWidgetForbidEnter(int x, int y, XLayoutContainer container) { |
|
container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); |
|
int screenX = (int) designer.getArea().getLocationOnScreen().getX(); |
|
int screenY = (int) designer.getArea().getLocationOnScreen().getY(); |
|
this.promptWindow.setSize(promptWindow.getPreferredSize()); |
|
this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); |
|
promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP); |
|
promptWindow.setVisible(true); |
|
} |
|
|
|
private void cancelPromptWidgetForbidEnter() { |
|
designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); |
|
promptWindow.setVisible(false); |
|
} |
|
|
|
|
|
/** |
|
* 按下 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mousePressed(MouseEvent e) { |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
pressX = oldX; |
|
pressY = oldY; |
|
offsetEventPoint(e); |
|
if (!stopEditing()) { |
|
return; |
|
} |
|
if (!designer.isFocusOwner()) { |
|
// 获取焦点,以便获取热键 |
|
designer.requestFocus(); |
|
} |
|
if (e.getButton() == MouseEvent.BUTTON1 && !designer.checkIfBeyondValidArea(e)) { |
|
|
|
Direction dir = selectionModel.getDirectionAt(e); |
|
if (!DesignerMode.isAuthorityEditing()) { |
|
stateModel.setDirection(dir); |
|
} |
|
|
|
if (dir == Location.outer) { |
|
if (designer.isDrawLineMode()) { |
|
designer.updateDrawLineMode(e); |
|
} else { |
|
if (selectionModel.hasSelectionComponent() |
|
&& selectionModel.getSelection().getRelativeBounds().contains( |
|
designer.getHorizontalScaleValue() + e.getX(), |
|
designer.getVerticalScaleValue() + e.getY())) { |
|
lastPressEvent = e; |
|
lastXCreator = selectionModel.getSelection().getSelectedCreator(); |
|
} else { |
|
stateModel.startSelecting(e); |
|
} |
|
} |
|
} else { |
|
stateModel.startResizing(e); |
|
} |
|
} |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
} |
|
|
|
private void offsetEventPoint(MouseEvent e){ |
|
int x = designer.getRelativeX(e.getX()); |
|
int y = designer.getRelativeY(e.getY()); |
|
e.translatePoint(x - e.getX(), y - e.getY()); |
|
} |
|
|
|
/** |
|
* 释放 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mouseReleased(MouseEvent e) { |
|
MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); |
|
MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
offsetEventPoint(e); |
|
if (e.isPopupTrigger()) { |
|
if (stateModel.isDragging()) { |
|
stateModel.draggingCancel(); |
|
} |
|
} else { |
|
if (designer.isDrawLineMode()) { |
|
if (stateModel.prepareForDrawLining()) { |
|
designer.getDrawLineHelper().setDrawLine(false); |
|
designer.getDrawLineHelper().createDefalutLine(); |
|
} |
|
} else if (stateModel.isSelecting()) { |
|
// 如果当前是区域选择状态,则选择该区域所含的组件 |
|
designer.selectComponents(e); |
|
} |
|
if (stateModel.isDragging()) { |
|
mouseDraggingRelease(e); |
|
} |
|
} |
|
lastPressEvent = null; |
|
lastXCreator = null; |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
if (isAutoFire(transEvent, clickEvent)) { |
|
// click只有在mouseReleased和mousePressed前后x/y坐标相等时才会被触发在mouseReleased之后 |
|
// 但是当使用者来回点击切换时 存在mouseReleased和mousePressed前后x/y坐标不相等的情况 即鼠标按下去的位置和鼠标释放的位置不相等 存在偏移 |
|
// 当这种偏移很小时 看起来就好像是点击了 实际上是手抖了或者鼠标轻微滑动了 所以这里对这种情况要有容错处理 |
|
mouseClicked(clickEvent); |
|
} |
|
} |
|
|
|
private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent ) { |
|
offsetEventPoint(transEvent); |
|
XCreator xCreator = designer.getComponentAt(transEvent); |
|
return (pressX != clickEvent.getX() || pressY != clickEvent.getY()) |
|
&& xCreator != null && xCreator.acceptType(XCardSwitchButton.class); |
|
} |
|
|
|
private void mouseDraggingRelease(MouseEvent e) { |
|
// 当前鼠标所在的组件 |
|
XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); |
|
if (designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null) { |
|
XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); |
|
if (selectionXCreator != null) { |
|
selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); |
|
} |
|
} |
|
dragBackupBounds = null; |
|
// 拉伸时鼠标拖动过快,导致所在组件获取会为空 |
|
if (hoveredComponent == null && e.getY() < 0) { |
|
// bug63538 |
|
// 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件 |
|
// 如果直接return,界面上已经进行了拖拽不能恢复 |
|
hoveredComponent = designer.getComponentAt(0, 0); |
|
} |
|
// 获取该组件所在的焦点容器 |
|
XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); |
|
|
|
if (container != null) { |
|
boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() |
|
&& container.acceptType(XWFitLayout.class); |
|
if (!formSubmit2Adapt) { |
|
// 如果是处于拖拽状态,则释放组件 |
|
stateModel.releaseDragging(e); |
|
} else { |
|
selectionModel.deleteSelection(); |
|
designer.setPainter(null); |
|
} |
|
cancelPromptWidgetForbidEnter(); |
|
} |
|
} |
|
|
|
/** |
|
* TODO 激活上下文菜单,待完善 |
|
* 6.56暂时不支持右键 bugid 8777 |
|
*/ |
|
private void triggerPopup(MouseEvent e) { |
|
XCreator creator = selectionModel.getSelection().getSelectedCreator(); |
|
if (creator == null) { |
|
return; |
|
} |
|
JPopupMenu popupMenu = null; |
|
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator); |
|
popupMenu = adapter.getContextPopupMenu(e); |
|
|
|
if (popupMenu != null) { |
|
popupMenu.show(designer, e.getX(), e.getY()); |
|
} |
|
// 通知组件已经被选择了 |
|
designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED); |
|
} |
|
|
|
/** |
|
* 移动 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mouseMoved(MouseEvent e) { |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
offsetEventPoint(e); |
|
XCreator component = designer.getComponentAt(e); |
|
|
|
setCoverPaneNotDisplay(component, e, false); |
|
|
|
if (processTopLayoutMouseMove(component, e)) { |
|
return; |
|
} |
|
if (component instanceof XEditorHolder) { |
|
XEditorHolder xcreator = (XEditorHolder) component; |
|
Rectangle rect = xcreator.getBounds(); |
|
int min = rect.x + rect.width / 2 - minMoveSize; |
|
int max = rect.x + rect.width / 2 + minMoveSize; |
|
if (e.getX() > min && e.getX() < max) { |
|
if (designer.getCursor().getType() != Cursor.HAND_CURSOR) { |
|
designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
|
} |
|
return; |
|
} else { |
|
if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { |
|
designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
|
} |
|
} |
|
} |
|
Direction dir = selectionModel.getDirectionAt(e); |
|
if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) { |
|
designer.updateDrawLineMode(e); |
|
} |
|
if (!DesignerMode.isAuthorityEditing()) { |
|
stateModel.setDirection(dir); |
|
} |
|
|
|
if (component.isReport()) { |
|
elementCaseMouseMoved(e, component); |
|
designer.repaint(); |
|
return; |
|
} |
|
|
|
processChartEditorMouseMove(component, e); |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
designer.repaint(); |
|
|
|
} |
|
|
|
private void processCoverPane(XCreator component) { |
|
// selected状态 不展示封面 |
|
XCreator xCreator = selectionModel.getSelection().getSelectedCreator(); |
|
boolean accept = xCreator == null || !ComparatorUtils.equals(xCreator.toData().getWidgetName(), component.toData().getWidgetName()) ||!xCreator.isSelected(); |
|
if (accept) { |
|
component.displayCoverPane(true); |
|
} |
|
} |
|
|
|
private boolean isShareConfigButton(MouseEvent e, XCreator component, Insets insets) { |
|
if (component.isShared()) { |
|
int minX = getParentPositionX(component, component.getX()) + component.getWidth() - insets.right - CoverReportPane.SHARE_CONF_BTN_W - designer.getHorizontalScaleValue(); |
|
int maxX = minX + CoverReportPane.SHARE_CONF_BTN_W; |
|
int minY = getParentPositionY(component, component.getY()) + insets.top - designer.getVerticalScaleValue(); |
|
int maxY = minY + CoverReportPane.SHARE_CONF_BTN_H; |
|
|
|
if ((e.getX() > minX - GAP) && e.getX() < maxX + GAP) { |
|
if (e.getY() > minY - GAP && e.getY() < maxY + GAP) { |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
private boolean isEditButton(MouseEvent e, XCreator component, Insets insets) { |
|
// 不显示编辑按钮 鼠标格式 |
|
if (component.getParent() instanceof XCreator) { |
|
XCreator parent = (XCreator) component.getParent(); |
|
if (parent.acceptType(XWTitleLayout.class) || component.acceptType(XWCardMainBorderLayout.class, XWAbsoluteLayout.class)) { |
|
return false; |
|
} |
|
} |
|
|
|
int innerWidth = component.getWidth() - insets.left - insets.right; |
|
int innerHeight = component.getHeight() - insets.top - insets.bottom; |
|
|
|
int minX = getParentPositionX(component, component.getX()) + insets.left + (innerWidth - CoverReportPane.EDIT_BTN_W) / 2 - designer.getHorizontalScaleValue(); |
|
int maxX = minX + CoverReportPane.EDIT_BTN_W; |
|
int minY = getParentPositionY(component, component.getY()) + insets.top + (innerHeight - CoverReportPane.EDIT_BTN_H) / 2 - designer.getVerticalScaleValue(); |
|
int maxY = minY + CoverReportPane.EDIT_BTN_H; |
|
if (e.getX() > minX - GAP && e.getX() < maxX + GAP) { |
|
if (e.getY() > minY - GAP && e.getY() < maxY + GAP) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
private void elementCaseMouseMoved(MouseEvent e, XCreator component) { |
|
xElementCase = (XElementCase) component; |
|
processCoverPane(component); |
|
processCoverMouseMove(component, e); |
|
} |
|
|
|
private void setCoverPaneNotDisplay(XCreator component, MouseEvent e, boolean isLinkedHelpDialog) { |
|
if (xChartEditor != null) { |
|
xChartEditor.displayCoverPane(false); |
|
} |
|
component.displayCoverPane(false); |
|
if (xTopLayoutContainer != null) { |
|
xTopLayoutContainer.setMouseEnter(false); |
|
} |
|
//不知道为什么要对XElementCase进行判断,但是直接return会有bug,所以把他放在最后 |
|
if (xElementCase != null) { |
|
int x = getParentPositionX(xElementCase, 0) - designer.getArea().getHorizontalValue(); |
|
int y = getParentPositionY(xElementCase, 0) - designer.getArea().getVerticalValue(); |
|
Rectangle rect = new Rectangle(x, y, xElementCase.getWidth(), xElementCase.getHeight()); |
|
if (!rect.contains(e.getPoint())) { |
|
xElementCase.displayCoverPane(false); |
|
} |
|
} |
|
designer.repaint(); |
|
} |
|
|
|
private boolean processTopLayoutMouseMove(XCreator component, MouseEvent e) { |
|
XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout(); |
|
if (parent != null) { |
|
xTopLayoutContainer = parent; |
|
xTopLayoutContainer.setMouseEnter(true); |
|
designer.repaint(); |
|
if (!xTopLayoutContainer.isEditable()) { |
|
processCoverMouseMove(parent, e); |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
private void processChartEditorMouseMove(XCreator component, MouseEvent e) { |
|
if (component instanceof XChartEditor) { |
|
xChartEditor = (XChartEditor) component; |
|
processCoverPane(component); |
|
processCoverMouseMove(component, e); |
|
|
|
} |
|
} |
|
|
|
private void processCoverMouseMove(XCreator component, MouseEvent e) { |
|
component.setHelpBtnOnFocus(false); |
|
Insets insets; |
|
if (component instanceof XBorderStyleWidgetCreator) { |
|
insets = ((XBorderStyleWidgetCreator) component).getInsets(); |
|
} else { |
|
insets = DEEFAULT_INSETS; |
|
} |
|
if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { |
|
designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
|
} |
|
if (isEditButton(e, component, insets)) { |
|
designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
|
} |
|
} |
|
|
|
private int getParentPositionX(XCreator comp, int x) { |
|
return comp.getParent() == null ? |
|
x : getParentPositionX((XCreator) comp.getParent(), comp.getParent().getX() + x); |
|
} |
|
|
|
private int getParentPositionY(XCreator comp, int y) { |
|
return comp.getParent() == null ? |
|
y : getParentPositionY((XCreator) comp.getParent(), comp.getParent().getY() + y); |
|
} |
|
|
|
/** |
|
* 拖拽 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mouseDragged(MouseEvent e) { |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
offsetEventPoint(e); |
|
if (DesignerMode.isAuthorityEditing()) { |
|
return; |
|
} |
|
boolean shiftSelecting = e.isShiftDown(); |
|
boolean ctrlSelecting = InputEventBaseOnOS.isControlDown(e); |
|
int currentCursorType = this.designer.getCursor().getType(); |
|
boolean shiftResizing = e.isShiftDown() && ( Cursor.SW_RESIZE_CURSOR <= currentCursorType && currentCursorType <= Cursor.E_RESIZE_CURSOR); |
|
|
|
if ((shiftSelecting || ctrlSelecting) && !shiftResizing && !stateModel.isSelecting()) { |
|
stateModel.startSelecting(e); |
|
} |
|
// 如果当前是左键拖拽状态,拖拽组件 |
|
if (stateModel.dragable()) { |
|
if (SwingUtilities.isRightMouseButton(e)) { |
|
return; |
|
} else { |
|
stateModel.dragging(e); |
|
// 获取e所在的焦点组件 |
|
XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); |
|
if (dragBackupBounds == null) { |
|
XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); |
|
if (selectingXCreator != null) { |
|
dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); |
|
} |
|
} |
|
// 拉伸时鼠标拖动过快,导致所在组件获取会为空 |
|
if (hotspot == null) { |
|
return; |
|
} |
|
// 获取焦点组件所在的焦点容器 |
|
XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); |
|
//提示组件是否可以拖入 |
|
promptUser(e.getX(), e.getY(), container); |
|
} |
|
} else if (designer.isDrawLineMode()) { |
|
if (stateModel.prepareForDrawLining()) { |
|
stateModel.drawLine(e); |
|
} |
|
} else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { |
|
// 如果是拖拽选择区域状态,则更新选择区域 |
|
stateModel.changeSelection(e); |
|
} else { |
|
if ((lastPressEvent == null) || (lastXCreator == null)) { |
|
return; |
|
} |
|
if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { |
|
//参数面板和自适应布局不支持拖拽 |
|
if (lastXCreator.isSupportDrag()) { |
|
designer.startDraggingComponent(lastXCreator, lastPressEvent, e.getX(), e.getY()); |
|
} |
|
e.consume(); |
|
lastPressEvent = null; |
|
} |
|
} |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
designer.repaint(); |
|
} |
|
|
|
//当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 |
|
private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout) { |
|
//双击的前后点击click为相同对象,过滤掉 |
|
if (clickedTopLayout == null || clickedTopLayout == clickingTopLayout) { |
|
return; |
|
} |
|
//位于同一层级的控件,父布局相同,过滤掉 |
|
if (clickingTopLayout != null && clickedTopLayout.getParent() == clickingTopLayout.getParent()) { |
|
return; |
|
} |
|
//前后点击的位于不同层级,要置为不可编辑 |
|
XLayoutContainer xLayoutContainer = (XLayoutContainer) clickedTopLayout.getParent(); |
|
if (xLayoutContainer == clickingTopLayout) { |
|
return; |
|
} |
|
if (xLayoutContainer != null) { |
|
xLayoutContainer.setEditable(false); |
|
setTopLayoutUnEditable((XLayoutContainer) clickedTopLayout.getParent(), clickingTopLayout); |
|
} |
|
} |
|
|
|
private boolean isCreatorInLayout(XCreator creator, XCreator layout) { |
|
if (creator.equals(layout)) { |
|
return true; |
|
} |
|
if (layout.getParent() != null) { |
|
return isCreatorInLayout(creator, (XCreator) layout.getParent()); |
|
} |
|
return false; |
|
} |
|
|
|
// 点击控件树,会触发此方法。如果在设计器中选中组件,则直接走 processTopLayoutMouseClick |
|
public void stopEditTopLayout(XCreator creator) { |
|
boolean isTabpaneSelected = creator instanceof XWCardLayout && creator.getParent().equals(clickTopLayout); |
|
if (clickTopLayout != null && (isTabpaneSelected || clickTopLayout.equals(creator))) { |
|
clickTopLayout.setEditable(false); |
|
} |
|
processTopLayoutMouseClick(creator); |
|
} |
|
|
|
public XCreator processTopLayoutMouseClick(XCreator creator) { |
|
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); |
|
if (topLayout != null) { |
|
if (clickTopLayout != null && !clickTopLayout.equals(topLayout) && !isCreatorInLayout(clickTopLayout, |
|
topLayout)) { |
|
clickTopLayout.setEditable(false); |
|
setTopLayoutUnEditable(clickTopLayout, topLayout); |
|
} |
|
clickTopLayout = topLayout; |
|
if (!topLayout.isEditable()) { |
|
creator = topLayout; |
|
} |
|
} else { |
|
if (clickTopLayout != null) { |
|
clickTopLayout.setEditable(false); |
|
setTopLayoutUnEditable(clickTopLayout, null); |
|
} |
|
} |
|
|
|
return creator; |
|
} |
|
|
|
/** |
|
* 点击 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mouseClicked(MouseEvent e) { |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
offsetEventPoint(e); |
|
selectionModel.getSelection().getTabList().clear(); |
|
XCreator creator = designer.getComponentAt(e); |
|
boolean isValidButton = e.getButton() == MouseEvent.BUTTON1 || e.getButton() == MouseEvent.BUTTON3; |
|
|
|
if (!isValidButton && !creator.acceptType(XCardSwitchButton.class)) { |
|
return; |
|
} |
|
|
|
XCreator oldCreator = creator; |
|
creator = processTopLayoutMouseClick(creator); |
|
|
|
if (creator != null) { |
|
// tab块处于未编辑状态 |
|
boolean uneditedTab = designer.getCursor().getType() != Cursor.HAND_CURSOR && creator.acceptType(XWCardMainBorderLayout.class) && !((XWCardMainBorderLayout) creator).isEditable(); |
|
// 点击不在tab块的button中 |
|
boolean clickedNonCardButton = !creator.acceptType(XCardAddButton.class, XCardSwitchButton.class); |
|
if (clickedNonCardButton && e.getClickCount() == 1 && designer.getCursor().getType() != Cursor.HAND_CURSOR) { |
|
setCoverPaneNotDisplay(creator, e, false); |
|
selectionModel.selectACreatorAtMouseEvent(e); |
|
refreshTopXCreator(); |
|
XCreator[] xCreators = selectionModel.getSelection().getSelectedCreators(); |
|
// 放到事件队尾执行 |
|
SwingUtilities.invokeLater(new Runnable() { |
|
@Override |
|
public void run() { |
|
for (XCreator xCreator : xCreators) { |
|
xCreator.setSelected(true); |
|
} |
|
} |
|
}); |
|
|
|
} else if (clickedNonCardButton && uneditedTab && responseTabLayout(oldCreator, e)) { |
|
// do nothing |
|
} else { |
|
creator.respondClick(this, e); |
|
} |
|
if (e.getButton() == MouseEvent.BUTTON3) { |
|
UIPopupMenu cellPopupMenu = creator.createPopupMenu(designer); |
|
if (cellPopupMenu != UIPopupMenu.EMPTY) { |
|
GUICoreUtils.showPopupMenu(cellPopupMenu, designer, oldX, oldY); |
|
} |
|
} |
|
creator.doLayout(); |
|
} |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
LayoutUtils.layoutRootContainer(designer.getRootComponent()); |
|
} |
|
|
|
private boolean responseTabLayout(XCreator creator, MouseEvent e) { |
|
LinkedList<XCreator> list = selectionModel.getSelection().getTabList(); |
|
if (creator.acceptType(XWCardMainBorderLayout.class)) { |
|
list.add(creator); |
|
} |
|
while (creator.getParent() instanceof XCreator) { |
|
creator = (XCreator) creator.getParent(); |
|
if (creator.acceptType(XWCardMainBorderLayout.class)) { |
|
list.add(creator); |
|
} |
|
} |
|
// 至少存在一层以上tab块的嵌套 |
|
if (list.size() > 1) { |
|
XWCardMainBorderLayout firstCreator = (XWCardMainBorderLayout) list.getFirst(); |
|
XWCardMainBorderLayout lastCreator = (XWCardMainBorderLayout) list.getLast(); |
|
// 内层tab响应事件 |
|
firstCreator.respondClick(this, e); |
|
setCoverPaneNotDisplay(firstCreator, e, false); |
|
final XCreator xCreator = selectionModel.getSelection().getSelectedCreator(); |
|
SwingUtilities.invokeLater(new Runnable() { |
|
@Override |
|
public void run() { |
|
xCreator.setSelected(true); |
|
// 外层tab展示阴影边框效果 |
|
lastCreator.setShowOuterShadowBorder(true); |
|
} |
|
}); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
|
|
/** |
|
* 离开 |
|
* |
|
* @param e 鼠标事件 |
|
*/ |
|
public void mouseExited(MouseEvent e) { |
|
int oldX = e.getX(); |
|
int oldY = e.getY(); |
|
offsetEventPoint(e); |
|
if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR && !(e.isShiftDown() || InputEventBaseOnOS.isControlDown(e))) { |
|
designer.setCursor(Cursor.getDefaultCursor()); |
|
} |
|
cancelPromptWidgetForbidEnter(); |
|
e.translatePoint(oldX - e.getX(), oldY - e.getY()); |
|
} |
|
|
|
/** |
|
* 开始编辑 |
|
* |
|
* @param creator 容器 |
|
* @param designerEditor 设计器 |
|
* @param adapter 适配器 |
|
*/ |
|
public void startEditing(XCreator creator, DesignerEditor<? extends JComponent> designerEditor, ComponentAdapter adapter) { |
|
if (designerEditor != null) { |
|
Rectangle rect = ComponentUtils.getRelativeBounds(creator); |
|
currentEditor = designerEditor; |
|
currentXCreator = creator; |
|
Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2); |
|
bounds.x += (rect.x - designer.getArea().getHorizontalValue()); |
|
bounds.y += (rect.y - designer.getArea().getVerticalValue()); |
|
designerEditor.getEditorTarget().setBounds(bounds); |
|
designer.add(designerEditor.getEditorTarget()); |
|
designer.invalidate(); |
|
designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
|
designerEditor.getEditorTarget().requestFocus(); |
|
designer.repaint(); |
|
} |
|
} |
|
|
|
/** |
|
* 停止编辑 |
|
* |
|
* @return 是否编辑成功 |
|
*/ |
|
public boolean stopEditing() { |
|
if (currentEditor != null) { |
|
designer.remove(currentEditor.getEditorTarget()); |
|
currentEditor.fireEditStoped(); |
|
|
|
Container container = currentXCreator.getParent(); |
|
|
|
if (container != null) { |
|
LayoutUtils.layoutRootContainer(container); |
|
} |
|
designer.invalidate(); |
|
designer.repaint(); |
|
currentXCreator.stopEditing(); |
|
currentXCreator = null; |
|
currentEditor = null; |
|
refreshTopXCreator(); |
|
return true; |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* 重置编辑控件大小 |
|
*/ |
|
public void resetEditorComponentBounds() { |
|
if (currentEditor == null) { |
|
return; |
|
} |
|
|
|
if (currentXCreator.getParent() == null) { |
|
stopEditing(); |
|
return; |
|
} |
|
|
|
Rectangle rect = ComponentUtils.getRelativeBounds(currentXCreator); |
|
Rectangle bounds = new Rectangle(1, 1, currentXCreator.getWidth() - 2, currentXCreator.getHeight() - 2); |
|
bounds.x += (rect.x - designer.getHorizontalScaleValue()); |
|
bounds.y += (rect.y - designer.getVerticalScaleValue()); |
|
if (currentXCreator instanceof XEditorHolder) { |
|
ToolTipEditor.getInstance().resetBounds((XEditorHolder) currentXCreator, bounds, currentEditor.getEditorTarget().getBounds()); |
|
} |
|
currentEditor.getEditorTarget().setBounds(bounds); |
|
} |
|
|
|
/** |
|
* 刷新顶层组件 |
|
* */ |
|
public void refreshTopXCreator(boolean isEditing){ |
|
designer.refreshTopXCreator(isEditing); |
|
} |
|
|
|
/** |
|
* 刷新顶层组件 |
|
* */ |
|
public void refreshTopXCreator(){ |
|
refreshTopXCreator(false); |
|
} |
|
|
|
}
|
|
|