帆软报表设计器源代码。
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.
 
 
 
 

961 lines
36 KiB

package com.fr.design.mainframe;
import com.fr.design.actions.UpdateAction;
import com.fr.design.constants.UIConstants;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWBorderLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIButtonUI;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.gui.itextfield.UINumberField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.guide.FvsGuidePane;
import com.fr.design.mainframe.share.ui.base.PopupMenuItem;
import com.fr.design.scrollruler.BaseRuler;
import com.fr.design.scrollruler.HorizontalRuler;
import com.fr.design.scrollruler.RulerLayout;
import com.fr.design.scrollruler.ScrollRulerComponent;
import com.fr.design.scrollruler.VerticalRuler;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.main.mobile.FormMobileAttr;
import com.fr.form.ui.container.WBodyLayoutType;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRScreen;
import com.fr.general.IOUtils;
import com.fr.stable.AssistUtils;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.AWTEvent;
import java.awt.Adjustable;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
public class FormArea extends JComponent implements ScrollRulerComponent {
private static final String SCALE_PLUS_COMMAND = "scale_plus";
private static final String SCALE_MINUS_COMMAND = "scale_minus";
public static final String FIX_LAYOUT_SWITCH_BUTTON = "fix_layout_switch_button";
public static final double DEFAULT_SLIDER = 100.0D;
private static final int ROTATIONS = 50;
public static final int SHOWVALMAX = 400;
public static final int SHOWVALMIN = 10;
private static final int RESIZE_PANE_GAP = 8;
private static final int MOBILE_ONLY_WIDTH = 375;
private static final int MOBILE_ONLY_HEIGHT = 560;
private FormDesigner designer;
private int horizontalValue = 0;
private int verticalValue = 0;
private int verticalMax = 0;
private int horicalMax = 0;
private FormScrollBar verScrollBar;
private FormScrollBar horScrollBar;
//显示和设置表单界面大小的控件
private UINumberField widthPane;
private UINumberField heightPane;
private JFormSliderPane slidePane;
private boolean isValid = true;
private UIButton fixLayoutSwitchButton;
private boolean isFixLayoutEditState;
public FormArea(FormDesigner designer) {
this(designer, true);
}
public FormArea(FormDesigner designer, boolean useScrollBar) {
this.designer = designer;
this.designer.setParent(this);
isValid = useScrollBar;
verScrollBar = new FormScrollBar(Adjustable.VERTICAL, this);
horScrollBar = new FormScrollBar(Adjustable.HORIZONTAL, this);
if (useScrollBar) {
this.setLayout(new FormRulerLayout());
designer.setBorder(new LineBorder(new Color(198, 198, 198)));
this.add(FormRulerLayout.FVS_GUIDE, new FvsGuidePane(this));
this.add(FormRulerLayout.CENTER, designer);
addFormSize();
this.add(FormRulerLayout.VERTICAL, verScrollBar);
this.add(FormRulerLayout.HIRIZONTAL, horScrollBar);
enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
widthPane.setEnabled(!designer.getTarget().getFormMobileAttr().isMobileOnly());
} else {
// 报表参数界面只要标尺和中心pane
this.setLayout(new RulerLayout());
this.add(RulerLayout.CENTER, designer);
addFormRuler();
}
this.setFocusTraversalKeysEnabled(false);
this.designer.addMouseWheelListener(new FormAreaMouseWheelHandler(this));
registerShortCutKey();
}
public FormScrollBar getVerticalScrollBar() {
return verScrollBar;
}
public FormScrollBar getHorizontalScrollBar() {
return horScrollBar;
}
public JFormSliderPane getSlidePane() {
return slidePane;
}
/**
* 注册缩放快捷键
* mac: command + 和 command -
* windows: ctr + 和 ctr -
*/
private void registerShortCutKey() {
this.registerKeyboardAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
int old_resolution = slidePane.getShowValue();
slidePane.setShowValue(old_resolution + SHOWVALMIN);
}
}, SCALE_PLUS_COMMAND, KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, DEFAULT_MODIFIER), WHEN_IN_FOCUSED_WINDOW);
this.registerKeyboardAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
int old_resolution = slidePane.getShowValue();
slidePane.setShowValue(old_resolution - SHOWVALMIN);
}
}, SCALE_MINUS_COMMAND, KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, DEFAULT_MODIFIER), WHEN_IN_FOCUSED_WINDOW);
}
public void onMobileAttrModified() {
FormMobileAttr formMobileAttr = designer.getTarget().getFormMobileAttr();
if (formMobileAttr.isMobileOnly()) {
widthPane.setValue(MOBILE_ONLY_WIDTH);
changeWidthPaneValue(MOBILE_ONLY_WIDTH);
heightPane.setValue(MOBILE_ONLY_HEIGHT);
changeHeightPaneValue(MOBILE_ONLY_HEIGHT);
}
widthPane.setEnabled(!formMobileAttr.isMobileOnly());
}
private UIButton createFixLayoutSwitchButton(){
UIButton button = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_No_Fix_Layout"));
button.setIcon(IOUtils.readIcon("/com/fr/base/images/share/filter_combo.png"));
button.setName(FIX_LAYOUT_SWITCH_BUTTON);
button.setUI(new UIButtonUI(){
@Override
protected void paintBorder(Graphics g, UIButton b) {
}
protected void doExtraPainting(UIButton b, Graphics2D g2d, int w, int h, String selectedRoles) {
if (isPressed(b) && b.isPressedPainted()) {
GUIPaintUtils.fillPressed(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles));
} else if (isRollOver(b)) {
GUIPaintUtils.fillRollOver(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted());
}
}
});
button.setHorizontalTextPosition(SwingConstants.LEFT);
UIPopupMenu popupMenu = new UIPopupMenu();
popupMenu.setPreferredSize(new Dimension(180, 59));
popupMenu.setOnlyText(true);
popupMenu.setBackground(UIConstants.DEFAULT_BG_RULER);
popupMenu.add(new PopupMenuItem(new Switch2NoFixLayoutAction()));
popupMenu.add(new PopupMenuItem(new Switch2FixLayoutAction()));
button.setComponentPopupMenu(popupMenu);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popupMenu.show(fixLayoutSwitchButton, 0, -59);
}
});
button.setVisible(!isAbsoluteBodyLayout());
return button;
}
private boolean isAbsoluteBodyLayout() {
return ((WFitLayout) designer.getRootComponent().toData()).getBodyLayoutType() == WBodyLayoutType.ABSOLUTE;
}
/**
* 增加表单的页面大小控制界面,包括手动修改和滑块拖动
*/
private void addFormSize() {
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {f};
double[] columnSize = {p, f, p, p, p, p, p, f, p};
UILabel tipsPane = new UILabel("form");
fixLayoutSwitchButton = createFixLayoutSwitchButton();
JPanel layoutSwitchPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
layoutSwitchPane.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 0));
layoutSwitchPane.add(fixLayoutSwitchButton);
widthPane = new UINumberField();
widthPane.setPreferredSize(new Dimension(60, 0));
heightPane = new UINumberField();
heightPane.setPreferredSize(new Dimension(60, 0));
slidePane = JFormSliderPane.getInstance();
JPanel resizePane = TableLayoutHelper.createCommonTableLayoutPane(
new JComponent[][]{{tipsPane, layoutSwitchPane, widthPane,
new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Indent_Pixel")),
new UILabel("x"), heightPane,
new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Indent_Pixel")),
new UILabel(),
slidePane}}, rowSize, columnSize, RESIZE_PANE_GAP);
this.add(FormRulerLayout.BOTTOM, resizePane);
setWidgetsConfig();
// 先初始话滑块及对应事件,然后获取分辨率调整容器的显示大小
slidePane.setEnabled(true);
slidePane.setVisible(true);
initCalculateSize();
slidePane.addValueChangeListener(showValSpinnerChangeListener);
slidePane.setShowValue(FRScreen.getFRScreenByDimension(Toolkit.getDefaultToolkit().getScreenSize()).getValue().intValue());
}
public void undoFixLayoutState(boolean isFixLayout) {
getFormEditor().getRootComponent().setFixLayout(isFixLayout);
this.switchLayout(isFixLayout);
}
public void switchBodyLayout(XLayoutContainer xLayoutContainer) {
this.fixLayoutSwitchButton.setVisible(xLayoutContainer.supportFixLayout());
this.switchLayout(false);
}
private void switchLayout(boolean isFixLayout) {
this.isFixLayoutEditState = isFixLayout;
this.fixLayoutSwitchButton.setText(isFixLayout ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Fix_Layout") :
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_No_Fix_Layout"));
FormMobileAttr formMobileAttr = designer.getTarget().getFormMobileAttr();
widthPane.setEnabled(!isFixLayout && !formMobileAttr.isMobileOnly());
heightPane.setEnabled(!isFixLayout);
}
private void setWidgetsConfig() {
widthPane.setHorizontalAlignment(widthPane.CENTER);
heightPane.setHorizontalAlignment(heightPane.CENTER);
widthPane.setMaxDecimalLength(0);
heightPane.setMaxDecimalLength(0);
//控件初始值就是根节点组件初始的宽和高
widthPane.setValue(designer.getRootComponent().getWidth());
heightPane.setValue(designer.getRootComponent().getHeight());
addWidthPaneListener();
addHeightPaneListener();
}
ChangeListener showValSpinnerChangeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
double value = slidePane.getShowValue();
value = value > SHOWVALMAX ? SHOWVALMAX : value;
value = value < SHOWVALMIN ? SHOWVALMIN : value;
scale((int) value);
}
};
private void scale(int value){
this.designer.setScale(value / DEFAULT_SLIDER);
FormArea.this.validate();
this.designer.repaint();
}
private void initCalculateSize() {
XLayoutContainer root = FormArea.this.designer.getRootComponent();
if (root.acceptType(XWFitLayout.class)) {
reCalculateDefaultRoot();
}
LayoutUtils.layoutContainer(root);
updateCreatorsBackupBound(root);
}
/**
* 给所有自适应布局内部的组件设置backupBounds
* @param creator
*/
private void updateCreatorsBackupBound(XCreator creator) {
if (creator.acceptType(XWFitLayout.class)) {
((XWFitLayout) creator).updateCreatorsBackupBound();
}
for (int i = 0; i < creator.getComponentCount(); i++) {
Component object = creator.getComponent(i);
if(object instanceof XCreator){
updateCreatorsBackupBound((XCreator) object);
}
} }
//设置宽度的控件及响应事件
private void addWidthPaneListener() {
widthPane.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int width = (int) ((UINumberField) evt.getSource()).getValue();
changeWidthPaneValue(width);
}
});
widthPane.addFocusListener(
new FocusAdapter() {
public void focusLost(FocusEvent e) {
// 失去焦点时,可以认为输入结束
int width = (int) ((UINumberField) e.getSource()).getValue();
changeWidthPaneValue(width);
}
});
}
private void changeWidthPaneValue(int width) {
XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
if (width != layout.toData().getContainerWidth()) {
reCalculateWidth(width);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
}
}
private void addHeightPaneListener() {
heightPane.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int height = (int) ((UINumberField) evt.getSource()).getValue();
changeHeightPaneValue(height);
}
});
heightPane.addFocusListener(
new FocusAdapter() {
public void focusLost(FocusEvent e) {
// 失去焦点时,可以认为输入结束
int height = (int) ((UINumberField) e.getSource()).getValue();
changeHeightPaneValue(height);
}
});
}
private void changeHeightPaneValue(int height) {
XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
if (height != layout.toData().getContainerHeight()) {
reCalculateHeight(height);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
}
}
private void reCalculateWidth(int width) {
XLayoutContainer root = FormArea.this.designer.getRootComponent();
if (root.acceptType(XWFitLayout.class)) {
XWFitLayout layout = (XWFitLayout) root;
Dimension d = new Dimension(layout.toData().getContainerWidth(), layout.toData().getContainerHeight());
Rectangle rec = new Rectangle(d);
// 容器大小改变时,设下backupBound为其之前的实际大小,以便调整贴边界的组件
layout.setBackupBound(rec);
int dW = width - rec.width;
if (dW == 0) {
return;
}
double percent = (double) dW / rec.width;
if (percent < 0 && !layout.canReduce(percent)) {
widthPane.setValue(rec.width);
return;
}
// 布局容器先设大小为实际的高和当前的宽,然后按此调整内部的组件
layout.setSize(width, rec.height);
layout.adjustCreatorsWidth(percent);
if (layout.getNeedAddWidth() > 0) {
widthPane.setValue(layout.getWidth());
// 调整之后清零调整量,否则再次缩放到最小值会产生干扰
layout.setNeedAddWidth(0);
}
doReCalculateRoot(width, rec.height, layout);
}
// REPORT-66771, 调整参数面板宽度
XLayoutContainer para = FormArea.this.designer.getParaComponent();
if (para != null && para instanceof XWParameterLayout) {
((XWParameterLayout) para).setParaWidth(width);
}
}
private void reCalculateHeight(int height) {
XLayoutContainer root = FormArea.this.designer.getRootComponent();
if (root.acceptType(XWFitLayout.class)) {
XWFitLayout layout = (XWFitLayout) root;
Dimension d = new Dimension(layout.toData().getContainerWidth(), layout.toData().getContainerHeight());
Rectangle rec = new Rectangle(d);
// 容器大小改变时,设下backupBound为其之前的实际大小
layout.setBackupBound(rec);
int dH = height - rec.height;
if (dH == 0) {
return;
}
double percent = (double) dH / rec.height;
if (percent < 0 && !layout.canReduce(percent)) {
heightPane.setValue(rec.height);
return;
}
layout.setSize(rec.width, height);
layout.adjustCreatorsHeight(percent);
if (layout.getNeedAddHeight() > 0) {
heightPane.setValue(layout.getHeight());
// 调整之后清零调整量,否则再次缩放到最小值会产生干扰
layout.setNeedAddHeight(0);
}
doReCalculateRoot(rec.width, height, layout);
}
}
/**
* 修改大小后,再根据屏幕分辨率调整下
*/
public void doReCalculateRoot(int width, int height, XWFitLayout layout) {
layout.getParent().setSize(width, height + designer.getParaHeight());
FormArea.this.validate();
}
/**
* 按照界面大小的百分比值调整root大小
*
*/
private void reCalculateDefaultRoot() {
XLayoutContainer root = FormArea.this.designer.getRootComponent();
if (root.acceptType(XWFitLayout.class)) {
XWFitLayout layout = (XWFitLayout) root;
XCreatorUtils.traverAndAdjust(layout);
layout.adjustCreatorsWhileSlide(0.0);
// 拖动滑块,先将内部组件百分比大小计算,再计算容器大小
Dimension d = new Dimension(layout.getWidth(), layout.getHeight());
// 自适应布局的父层是border
if (layout.getParent() != null) {
int paraHeight = designer.getParaHeight();
if (paraHeight > 0) {
designer.setParaHeight(paraHeight);
XWBorderLayout parent = (XWBorderLayout) layout.getParent();
parent.toData().setNorthSize(paraHeight);
parent.removeAll();
parent.add(designer.getParaComponent(), WBorderLayout.NORTH);
parent.add(designer.getRootComponent(), WBorderLayout.CENTER);
}
layout.getParent().setSize(d.width, d.height + paraHeight);
// 调整自适应布局大小后,同步调整参数界面和border大小,此时刷新下formArea
FormArea.this.validate();
}
}
}
/**
* 增加刻度条
*/
public void addFormRuler() {
BaseRuler vRuler = new VerticalRuler(this);
BaseRuler hRuler = new HorizontalRuler(this);
this.add(RulerLayout.VRULER, vRuler);
this.add(RulerLayout.HRULER, hRuler);
}
/**
* 鼠标滚轮事件
* 由于表单设计界面要求: 容器大小大于界面时,滚动条才可以拖动,所以不支持滚动无限往下滚
*/
@Override
protected void processMouseWheelEvent(java.awt.event.MouseWheelEvent evt) {
int id = evt.getID();
switch (id) {
case MouseEvent.MOUSE_WHEEL: {
onMouseWheelScroll(evt);
break;
}
default:
}
}
private void onMouseWheelScroll(MouseWheelEvent evt) {
int value = this.verScrollBar.getValue() + evt.getWheelRotation() * ROTATIONS;
value = Math.max(0, Math.min(value, verticalMax));
doLayout(); //加dolayout是因为每次滚动都要重置 Max的大小
this.verScrollBar.setValue(value);
}
/**
* 返回表单容器的中心designer
* getFormEditor.
*/
public FormDesigner getFormEditor() {
return designer;
}
private boolean shouldSetScrollValue(XCreator creator) {
return !isValid || designer.isRoot(creator) || getDesignerWidth() >= designer.getRootComponent().getWidth();
}
/**
* 设置界面内的组件可见以及水平垂直滚动条的值
* (除了根容器,拖入组件进来时如果大小超过当前界面大小,必须设置滚动条值,否则滚动条默认不显示)
*
* @param creator 控件
*/
public void scrollPathToVisible(XCreator creator) {
creator.seleteRelatedComponent(creator);
if (!ComponentUtils.isComponentVisible(creator) && !designer.isRoot(creator)) {
designer.makeVisible(creator);
}
if (shouldSetScrollValue(creator)) {
return;
}
//获取在容器的绝对位置
Rectangle rec = ComponentUtils.getRelativeBounds(creator);
// 组件实际大小、位置要考虑缩放
int dWidth = getDesignerWidth();
double recRealWidth = rec.width * designer.getScale();
double recRealX = rec.x * designer.getScale();
if (recRealWidth <= dWidth && recRealX < getHorizontalValue()) {
//在边界内部且x位置小于水平滚动条的值
horScrollBar.setValue((int) recRealX);
} else if (recRealX + recRealWidth > dWidth + horizontalValue) {
//超出边界宽度
horScrollBar.setValue((int) (recRealX + recRealWidth - dWidth));
}
int dHeight = getDesignerHeight();
double recRealHeight = rec.height * designer.getScale();
double recRealY = rec.y * designer.getScale();
if (recRealHeight < dHeight && recRealY < getVerticalValue()) {
//在边界内部且y位置小于竖直滚动条的值
verScrollBar.setValue((int) recRealY);
} else if (recRealY + recRealHeight > dHeight + verticalValue) {
//超出边界高度
verScrollBar.setValue((int) (recRealY + recRealHeight - dHeight));
}
}
/**
* 容器布局
*/
public void doLayout() {
layout();
if (isValid) {
XLayoutContainer root = designer.getRootComponent();
setScrollBarProperties((int) (root.getWidth()*designer.getScale() - designer.getWidth()), horScrollBar, horizontalValue);
//计算滚动条值的时候应该算上参数面板的高度
setScrollBarProperties((int) (designer.getParaHeight() + root.getHeight()*designer.getScale() - designer.getHeight()), verScrollBar, verticalValue);
}
}
/**
* 设置滚动条的属性
*/
private void setScrollBarProperties(int value, FormScrollBar bar, int oldValue) {
if (value == 0 && isScrollNotVisible(bar)) {
return;
}
if (value <= 0) {
// 界面有滚动条时,手动缩小容器宽度到界面内,重置滚动条值和max
setScrollBarMax(0, bar);
bar.setMaximum(0);
bar.setValue(0);
bar.setEnabled(false);
} else {
setScrollBarMax(value, bar);
bar.setEnabled(true);
bar.setMaximum(value);
bar.setValue(value);
//参数面板拖拽过程中value一直为当前value
bar.setValue(oldValue);
}
}
private boolean isScrollNotVisible(FormScrollBar bar) {
if (bar.getOrientation() == Adjustable.VERTICAL) {
return verticalMax == 0;
} else {
return horicalMax == 0;
}
}
private void setScrollBarMax(int max, FormScrollBar bar) {
if (bar.getOrientation() == Adjustable.VERTICAL) {
verticalMax = max;
} else {
horicalMax = max;
}
}
/**
* 返回designer的最小高度
*
* @return int
*/
public int getMinHeight() {
return designer.getDesignerMode().getMinDesignHeight();
}
/**
* 返回designer的最小宽度
*
* @return int
*/
public int getMinWidth() {
return designer.getDesignerMode().getMinDesignWidth();
}
/**
* getRulerLengthUnit
*
* @return short
*/
public short getRulerLengthUnit() {
return -1;
}
/**
* 返回水平滚动条的value
*
* @return int
*/
public int getHorizontalValue() {
return horizontalValue;
}
/**
* 设置水平滚动条的value
*
* @param newValue
*/
public void setHorizontalValue(int newValue) {
this.horizontalValue = newValue;
}
/**
* 返回竖直滚动条的value
*
* @return
*/
public int getVerticalValue() {
return verticalValue;
}
/**
* 竖直滚动条赋值
*
* @param newValue
*/
public void setVerticalValue(int newValue) {
this.verticalValue = newValue;
}
/**
* 返回当前designer的高度
*
* @return height
*/
public int getDesignerHeight() {
return designer.getHeight();
}
/**
* 返回当前designer的宽度
*
* @return
*/
public int getDesignerWidth() {
return designer.getWidth();
}
/**
* 返回宽度控件的value
*
* @return 宽度
*/
public double getWidthPaneValue() {
return widthPane.getValue();
}
/**
* 设置宽度值
*
* @param value 值
*/
public void setWidthPaneValue(int value) {
widthPane.setValue(value);
}
/**
* 设置高度值
*
* @param value 值
*/
public void setHeightPaneValue(int value) {
heightPane.setValue(value);
}
/**
* 返回高度控件的value
*
* @return 高度
*/
public double getHeightPaneValue() {
return heightPane.getValue();
}
/**
* 返回界面大小的百分比值
*
* @return 百分比值
*/
public double getSlideValue() {
return slidePane.getShowValue();
}
/**
* 返回界面区域大小
*
* @return Dimension
*/
public Dimension getAreaSize() {
return new Dimension(horScrollBar.getMaximum(), verScrollBar.getMaximum());
}
/**
* setAreaSize
*
* @param totalSize
* @param horizontalValue
* @param verticalValue
*/
public void setAreaSize(Dimension totalSize, int horizontalValue, int verticalValue, double width, double height, double slide) {
this.verticalMax = (int) totalSize.getHeight();
this.horicalMax = (int) totalSize.getHeight();
// 撤销时会refreshRoot,导致layout大小变为默认大小
// 按照之前设置的宽高和百分比重置下容器size
if ( !AssistUtils.equals(width, widthPane.getValue()) ) {
widthPane.setValue(width);
reCalculateWidth((int) width);
}
if ( !AssistUtils.equals(height, heightPane.getValue()) ) {
heightPane.setValue(height);
reCalculateHeight((int) height);
}
traverAndAdjust(designer.getRootComponent());
this.slidePane.setShowValue((int) slide);
}
// 撤销时先refreshRoot了,此处去掉内边距再增加间隔,循环遍历布局,调整fitlayout布局的间隔
private void traverAndAdjust(XCreator creator) {
if (creator instanceof XWFitLayout) {
XWFitLayout temp = (XWFitLayout) creator;
temp.moveContainerMargin();
temp.addCompInterval(temp.getAcualInterval());
}
for (int i = 0; i < creator.getComponentCount(); i++) {
Object object = creator.getComponent(i);
if (object instanceof XCreator){
traverAndAdjust((XCreator) object);
}
}
}
/**
* 计算滚动条的值和max
*
* @param oldmax 之前最大值
* @param max 当前最大值
* @param newValue 当前value
* @param oldValue 之前value
* @param visi designer的大小
* @param orientation 滚动条方向
* @return 计算后的值和max
*/
@Override
public Point calculateScroll(int oldmax, int max, int newValue, int oldValue, int visi, int orientation) {
int scrollMax = orientation == 1 ? verticalMax : horicalMax;
//防止滚动条到达低端还可以继续点击移动(滚动条最大范围不变时,newValue要在范围之内)
if (oldmax == scrollMax + visi && newValue > scrollMax) {
return new Point(scrollMax, oldmax);
}
return new Point(newValue, max);
}
private class FormRulerLayout extends RulerLayout {
public static final String FVS_GUIDE = "FvsGuide";
private static final int DESIGNER_WIDTH = 960;
private static final int DESIGNER_HEIGHT = 540;
private static final int TOPGAP = 8;
private int DESIGNERWIDTH = DESIGNER_WIDTH;
private int DESIGNERHEIGHT = DESIGNER_HEIGHT;
private FvsGuidePane fvsGuidePane;
public FormRulerLayout() {
super();
}
@Override
public void addLayoutComponent(String name, Component comp) {
super.addLayoutComponent(name, comp);
if (isValid && ComparatorUtils.equals(name, FVS_GUIDE)) {
fvsGuidePane = (FvsGuidePane) comp;
}
}
/**
* 表单用的layout,当前不需要标尺
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int top = insets.top;
int left = insets.left;
int bottom = target.getHeight() - insets.bottom;
int right = target.getWidth() - insets.right;
Dimension resize = resizePane.getPreferredSize();
Dimension hbarPreferredSize = null;
Dimension vbarPreferredSize = null;
resizePane.setBounds(left, bottom - resize.height, right, resize.height);
if (horScrollBar != null) {
hbarPreferredSize = horScrollBar.getPreferredSize();
vbarPreferredSize = verScrollBar.getPreferredSize();
horScrollBar.setBounds(left, bottom - hbarPreferredSize.height - resize.height, right - BARSIZE, hbarPreferredSize.height);
verScrollBar.setBounds(right - vbarPreferredSize.width, top, vbarPreferredSize.width, bottom - BARSIZE - resize.height);
}
FormDesigner dg = ((FormDesigner) designer);
XLayoutContainer root = dg.getRootComponent();
if (root.acceptType(XWFitLayout.class)) {
DESIGNERWIDTH = root.getWidth();
DESIGNERHEIGHT = dg.hasWAbsoluteLayout() ? root.getHeight() + dg.getParaHeight() : root.getHeight();
}
Rectangle rec = new Rectangle(left + (right - DESIGNERWIDTH) / 2, TOPGAP, right, bottom);
//是否为表单
if (isValid) {
if (hbarPreferredSize == null) {
throw new IllegalArgumentException("hbarPreferredSize can not be null!");
}
DESIGNERHEIGHT = bottom - hbarPreferredSize.height - resize.height - TOPGAP * 2;
DESIGNERWIDTH = right - vbarPreferredSize.width;
int designerLeft = left + (verScrollBar.getX() - DESIGNERWIDTH) / 2;
int designerTop = top + (horScrollBar.getY() - DESIGNERHEIGHT) / 2;
if (fvsGuidePane != null) {
Dimension fvsGuidePreferredSize = fvsGuidePane.getPreferredSize();
fvsGuidePane.setBounds(left, top, right - BARSIZE - 2, fvsGuidePreferredSize.height);
DESIGNERHEIGHT -= fvsGuidePreferredSize.height;
designerTop += fvsGuidePreferredSize.height;
}
rec = new Rectangle(designerLeft, designerTop, DESIGNERWIDTH, DESIGNERHEIGHT);
}
// designer是整个表单设计界面中的面板部分,目前只放自适应布局和参数界面。
designer.setBounds(rec);
}
}
@Override
public void removeLayoutComponent(Component comp) {
super.removeLayoutComponent(comp);
if (isValid && ComparatorUtils.equals(comp, fvsGuidePane)) {
fvsGuidePane = null;
}
}
@Override
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = super.preferredLayoutSize(target);
if (isValid && fvsGuidePane != null) {
dim.height += fvsGuidePane.getPreferredSize().height;
}
return dim;
}
}
@Override
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = super.minimumLayoutSize(target);
if (isValid && fvsGuidePane != null) {
Dimension dim1 = fvsGuidePane.getMinimumSize();
dim.height += dim1.height;
}
return dim;
}
}
}
public boolean isFixLayout(){
return this.isFixLayoutEditState;
}
class Switch2NoFixLayoutAction extends UpdateAction{
public Switch2NoFixLayoutAction(){
this.putValue(Action.SMALL_ICON, null);
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_No_Fix_Layout"));
this.setSmallIcon("/com/fr/design/form/images/no_fix_layout_icon.png");
}
@Override
public void actionPerformed(ActionEvent e) {
getFormEditor().getRootComponent().setFixLayout(false);
switchLayout(false);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
DesignerContext.getDesignerFrame().refresh();
}
}
class Switch2FixLayoutAction extends UpdateAction{
public Switch2FixLayoutAction(){
this.putValue(Action.SMALL_ICON, null);
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Fix_Layout"));
this.setSmallIcon("/com/fr/design/form/images/fix_layout_icon.png");
}
@Override
public void actionPerformed(ActionEvent e) {
getFormEditor().getRootComponent().setFixLayout(true);
switchLayout(true);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
DesignerContext.getDesignerFrame().refresh();
}
}
}