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

824 lines
36 KiB

package com.fr.design.gui.xpane;
import com.fr.base.GraphHelper;
import com.fr.base.Style;
import com.fr.base.Utils;
import com.fr.base.background.ImageBackground;
import com.fr.base.background.ImageFileBackground;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.event.UIObserver;
import com.fr.design.event.UIObserverListener;
import com.fr.design.gui.frpane.ImgChooseWrapper;
import com.fr.design.gui.frpane.UIPercentDragPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIButtonUI;
import com.fr.design.gui.ibutton.UIColorButton;
import com.fr.design.gui.icombobox.LineComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.backgroundpane.ImagePreviewPane;
import com.fr.design.style.background.image.ImageFileChooser;
import com.fr.design.style.color.NewColorSelectBox;
import com.fr.env.utils.DesignerInteractionHistory;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.general.Background;
import com.fr.general.IOUtils;
import com.fr.i18n.UrlI18nManager;
import com.fr.stable.Constants;
import com.fr.stable.GraphDrawHelper;
import com.fr.stable.ProjectLibrary;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.RoundRectangle2D;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
/**
* @author Starryi
* @version 10.0.18
* Created by Starryi on 2021/7/2
*
* 可配置图片类型边框的样式设置面板
*/
public class BorderLineAndImagePane extends JPanel implements UIObserver {
private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH;
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT);
private final String TWEAK_NINE_POINT_HELP_URL = "https://help.fanruan.com/finereport/doc-view-4135.html";
private UIObserverListener uiObserverListener;
private BorderLineAndImageComboBox borderLineCombo;
private NewColorSelectBox borderColorPane;
private ImagePreviewPane imagePreviewPane;
private UIButton chooseImageButton;
private UIButton tweakNinePointHelpButton;
private UIButton tweakNinePointButton;
private UIPercentDragPane borderImageOpacityPane;
private NinePointImageTweakDialogPane tweakPane;
private ImageFileChooser imageFileChooser;
private int[] ninePoint = new int[] {-1, -1, -1, -1};
public BorderLineAndImagePane(boolean supportBorderImage) {
this.initComponents(supportBorderImage);
this.initLayout();
}
private void initComponents(boolean supportBorderImage) {
borderLineCombo = new BorderLineAndImageComboBox(supportBorderImage);
borderColorPane = new NewColorSelectBox(145);
imagePreviewPane = new ImagePreviewPane() {{
setImageStyle(Style.DEFAULT_STYLE);
}};
chooseImageButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Image_Select_Picture"));
tweakNinePointHelpButton = new UIButton(IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_border_image_help.png"));
tweakNinePointHelpButton.setUI(new BasicButtonUI());
tweakNinePointHelpButton.setBorderPainted(false);
tweakNinePointHelpButton.setBorder(null);
tweakNinePointHelpButton.setContentAreaFilled(false);
tweakNinePointHelpButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(new URI(UrlI18nManager.getInstance().getI18nUrl("nine.point.help")));
} catch (IOException | URISyntaxException ioException) {
ioException.printStackTrace();
}
}
});
tweakNinePointButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill"));
borderImageOpacityPane = new UIPercentDragPane();
}
private JPanel createBorderLineComposedPane() {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
return TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Line")), this.borderLineCombo}},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, 0);
}
private JPanel createBorderColorComposedPane() {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
return TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Color")), this.borderColorPane}},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, 0);
}
private JPanel createBorderImageComposePane() {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p, p, p, p, p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
JPanel borderedImagePreviewPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
borderedImagePreviewPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 5));
borderedImagePreviewPane.setPreferredSize(new Dimension(145, 145));
borderedImagePreviewPane.add(imagePreviewPane, BorderLayout.CENTER);
JPanel tweakNinePointComposedPane = new JPanel();
tweakNinePointComposedPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
tweakNinePointButton.setPreferredSize(new Dimension(145, 16));
tweakNinePointComposedPane.add(tweakNinePointHelpButton);
tweakNinePointComposedPane.add(tweakNinePointButton);
return TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{
{null, borderedImagePreviewPane},
{null, chooseImageButton},
{tweakNinePointComposedPane, null},
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))},
{null, this.borderImageOpacityPane}
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
}
private void initImageFileChooserIfNotExist() {
if (imageFileChooser == null) {
imageFileChooser = new ImageFileChooser();
imageFileChooser.setMultiSelectionEnabled(false);
}
}
private void initImageFileChooserDirectory() {
DesignerInteractionHistory history = DesignerInteractionHistory.getInstance();
String lastUsedBorderImageDirPath = history.getLastSelectedBorderImageDir();
File lastUsedBorderImageDir = StringUtils.isNotEmpty(lastUsedBorderImageDirPath) ? new File(lastUsedBorderImageDirPath) : null;
File inbuiltBorderImagesDir = new File(StableUtils.pathJoin(ProjectLibrary.getInstance().getLibHome(), ProjectConstants.ASSETS_NAME, "border_images"));
if (lastUsedBorderImageDir!= null && lastUsedBorderImageDir.exists()) {
imageFileChooser.setCurrentDirectory(lastUsedBorderImageDir);
} else if (inbuiltBorderImagesDir.exists()) {
imageFileChooser.setCurrentDirectory(inbuiltBorderImagesDir);
}
}
protected void initNinePointTweakPaneIfNotExist() {
if (tweakPane == null) {
tweakPane = new NinePointImageTweakDialogPane();
}
}
private void initLayout() {
this.setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1));
this.add(this.createBorderLineComposedPane(), BorderLayout.NORTH, 0);
this.add(this.createBorderColorComposedPane(), BorderLayout.CENTER, 1);
this.add(this.createBorderImageComposePane(), BorderLayout.SOUTH, 2);
getComponent(1).setVisible(false);
getComponent(2).setVisible(false);
this.borderLineCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getComponent(1).setVisible(borderLineCombo.isSelectedBorderLine());
getComponent(2).setVisible(borderLineCombo.isSelectedBorderImage());
if (!borderLineCombo.isSelectedBorderLine()) {
borderColorPane.setSelectObject(Color.BLACK);
}
if (!borderLineCombo.isSelectedBorderImage()) {
imagePreviewPane.setImageWithSuffix(null);
tweakNinePointButton.setEnabled(false);
}
fireStateChanged();
}
});
this.chooseImageButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initImageFileChooserIfNotExist();
initImageFileChooserDirectory();
int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame());
if (returnVal == JFileChooser.APPROVE_OPTION) {
DesignerInteractionHistory history = DesignerInteractionHistory.getInstance();
File selectedDirectory = imageFileChooser.getSelectedFile().getParentFile();
history.setLastSelectedBorderImageDir(selectedDirectory.getPath());
}
ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, DEFAULT_IMAGE_LAYOUT_STYLE, new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Image image = imagePreviewPane.getImage();
ninePoint = new int[4];
ninePoint[0] = ninePoint[2] = (image != null ? image.getWidth(null) / 3 : -1);
ninePoint[1] = ninePoint[3] = (image != null ? image.getHeight(null) / 3 : -1);
borderImageOpacityPane.populateBean(1.0);
if (image != null) {
tweakNinePointButton.setEnabled(true);
}
fireStateChanged();
}
}).dealWithImageFile(returnVal);
}
});
this.tweakNinePointButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
initNinePointTweakPaneIfNotExist();
if (imagePreviewPane.getImage() != null) {
tweakPane.previewPane.setNinePoint(ninePoint);
BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(BorderLineAndImagePane.this));
dialog.addDialogActionListener(new DialogActionAdapter() {
@Override
public void doOk() {
ninePoint = Arrays.copyOf(tweakPane.previewPane.getNinePoint(), 4);
fireStateChanged();
}
});
dialog.setVisible(true);
}
}
});
}
public void populateBean(LayoutBorderStyle style) {
int borderLine = style.getBorder();
Color borderColor = style.getColor();
this.borderLineCombo.setSelectedLineStyle(borderLine);
this.borderColorPane.setSelectObject(borderColor);
Background borderImage = style.getBorderImage();
if (borderImage instanceof ImageBackground) {
// 图片类型边框
Image image = ((ImageBackground) borderImage).getImage();
int[] ninePoint = ((ImageBackground) borderImage).getNinePoint();
if (image != null) {
this.borderLineCombo.selectBorderImage();
this.imagePreviewPane.setImageWithSuffix(((ImageBackground) borderImage).getImageWithSuffix());
this.tweakNinePointButton.setEnabled(true);
this.borderImageOpacityPane.populateBean(style.getBorderImageOpacity());
if (ninePoint != null && ninePoint.length == 4 && ninePoint[0] > 0 && ninePoint[1] > 0 && ninePoint[2] > 0 && ninePoint[3] > 0) {
this.ninePoint = Arrays.copyOf(ninePoint, 4);
} else {
this.ninePoint = new int[4];
this.ninePoint[0] = this.ninePoint[2] = image.getWidth(null) / 3;
this.ninePoint[1] = this.ninePoint[3] = image.getHeight(null) / 3;
}
getComponent(1).setVisible(false);
getComponent(2).setVisible(true);
return;
}
}
if (borderLine == Constants.LINE_NONE) {
getComponent(1).setVisible(false);
getComponent(2).setVisible(false);
return;
} else {
getComponent(1).setVisible(true);
getComponent(2).setVisible(false);
}
this.borderLineCombo.setSelectedLineStyle(style.getBorder());
this.borderColorPane.setSelectObject(style.getColor());
}
public void updateBean(LayoutBorderStyle style) {
style.setBorder(this.borderLineCombo.getSelectedLineStyle());
style.setColor(this.borderColorPane.getSelectObject());
style.setBorderImage(null);
if (this.borderLineCombo.isSelectedBorderImage()) {
Image image = this.imagePreviewPane.getImage();
if (image != null) {
ImageBackground newImageBackground = new ImageFileBackground(this.imagePreviewPane.getImageWithSuffix(), Constants.IMAGE_EXTEND);
newImageBackground.setNinePoint(Arrays.copyOf(ninePoint, 4));
style.setBorderImage(newImageBackground);
style.setBorderImageOpacity((float)borderImageOpacityPane.updateBean());
}
}
}
private void fireStateChanged() {
if (uiObserverListener != null) {
uiObserverListener.doChange();
}
}
@Override
public void registerChangeListener(UIObserverListener listener) {
this.uiObserverListener = listener;
}
@Override
public boolean shouldResponseChangeListener() {
return true;
}
protected UIButtonUI createButtonUI(final UIColorButton uiColorButton) {
return new UIButtonUI() {
public void paint(Graphics g, JComponent c) {
UIButton b = (UIButton) c;
g.setColor(Color.black);
GraphHelper.draw(g, new RoundRectangle2D.Double(1, 1, b.getWidth() - 2, b.getHeight() - 2, 0, 0), 1);
if (b.getModel().isEnabled()) {
g.setColor(uiColorButton.getColor());
} else {
g.setColor(new Color(Utils.filterRGB(uiColorButton.getColor().getRGB(), 50)));
}
g.fillRect(2, 2, b.getWidth() - 3, b.getHeight() - 3);
}
};
}
protected static class BorderLineAndImageComboBox extends LineComboBox {
public static final int LINE_PICTURE = -1;
public final static int[] BORDER_LINE_AND_IMAGE_STYLE_ARRAY = new int[] {
Constants.LINE_NONE,
LINE_PICTURE,
Constants.LINE_THIN, //1px
Constants.LINE_MEDIUM, //2px
Constants.LINE_THICK, //3px
};
public final static int[] BORDER_LINE_STYLE_ARRAY = new int[] {
Constants.LINE_NONE,
Constants.LINE_THIN, //1px
Constants.LINE_MEDIUM, //2px
Constants.LINE_THICK, //3px
};
private boolean supportBorderImage = false;
public BorderLineAndImageComboBox(boolean supportBorderImage) {
super(supportBorderImage ? BORDER_LINE_AND_IMAGE_STYLE_ARRAY : BORDER_LINE_STYLE_ARRAY);
this.supportBorderImage = supportBorderImage;
}
@Override
protected String toStringFromStyle(int style) {
if (style == LINE_PICTURE) {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image");
}
return super.toStringFromStyle(style);
}
public boolean isSelectedBorderLine() {
Object object = getSelectedItem();
if (object != null) {
int value = (int) object;
return value > 0;
}
return false;
}
public boolean isSelectedBorderImage() {
Object object = getSelectedItem();
if (object != null) {
int value = (int) object;
return value == LINE_PICTURE;
}
return false;
}
public void selectBorderImage() {
if (supportBorderImage) {
this.setSelectedIndex(1);
}
}
}
private class NinePointImageTweakDialogPane extends BasicPane {
public final NinePointLinePreviewPane previewPane = new NinePointLinePreviewPane();
public NinePointImageTweakDialogPane() {
this.initComponents();
}
private void initComponents() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder());
add(previewPane, BorderLayout.CENTER);
previewPane.setPreferredSize(new Dimension(615, 462));
previewPane.setBorder(BorderFactory.createEmptyBorder());
}
@Override
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill");
}
}
private class NinePointLinePreviewPane extends JPanel implements MouseMotionListener, MouseListener {
public final Color BACKGROUND_PANE_COLOR = Color.WHITE;
public final Color BACKGROUND_IMG_COLOR = Color.lightGray;
public final Color DIVIDER_BACKGROUND_COLOR = new Color(235, 29, 31);
public final Color DIVIDER_FOREGROUND_COLOR = Color.WHITE;
public final Color HINT_BACKGROUND_COLOR = new Color(0, 215, 215);
public final Color HINT_FOREGROUND_COLOR = Color.WHITE;
public final int HINT_GAP = 5;
public final int PADDING = 20;
public final Cursor E_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_e.png"),
new Point(8, 8), "E_DRAG_CURSOR");
public final Cursor S_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_s.png"),
new Point(8, 8), "S_DRAG_CURSOR");
public final Cursor W_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_w.png"),
new Point(8, 8), "W_DRAG_CURSOR");
public final Cursor N_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_n.png"),
new Point(8, 8), "N_DRAG_CURSOR");
public final Cursor NE_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_ne.png"),
new Point(8, 8), "NE_DRAG_CURSOR");
public final Cursor NW_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_nw.png"),
new Point(8, 8), "NW_DRAG_CURSOR");
public final Cursor SE_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_se.png"),
new Point(8, 8), "SE_DRAG_CURSOR");
public final Cursor SW_DRAG_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor(
IOUtils.readImage("/com/fr/design/images/control/icon_cursor_drag_sw.png"),
new Point(8, 8), "SW_DRAG_CURSOR");
private int ninePointLeft = -1;
private int ninePointTop = -1;
private int ninePointRight = -1;
private int ninePointBottom = -1;
private static final int MIN_NINE_POINT = 0;
private int imgWidth;
private int imgHeight;
private int scaleImgWidth;
private int scaleImgHeight;
private int scaleImgX;
private int scaleImgY;
private double imageScale = 1.0;
private boolean draggingLeftDivider = false;
private boolean draggingRightDivider = false;
private boolean draggingTopDivider = false;
private boolean draggingBottomDivider = false;
public NinePointLinePreviewPane() {
this.setLayout(null);
this.addMouseMotionListener(this);
this.addMouseListener(this);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(BACKGROUND_PANE_COLOR);
g2d.fillRect(0, 0, getWidth(), getHeight());
Image image = imagePreviewPane.getImage();
imgWidth = image.getWidth(null);
imgHeight = image.getHeight(null);
int autoFixAreaWidth = getWidth() - 2 * PADDING;
int autoFixAreaHeight = getHeight() - 2 * PADDING;
int autoFixAreaX = PADDING;
int autoFixAreaY = PADDING;
if ((imgWidth * 1.0F / imgHeight) > (autoFixAreaWidth * 1.0F / autoFixAreaHeight)) {
scaleImgWidth = autoFixAreaWidth;
scaleImgHeight = (int) (1.0F * scaleImgWidth * imgHeight / imgWidth);
scaleImgX = autoFixAreaX;
scaleImgY = (autoFixAreaHeight - scaleImgHeight) / 2 + autoFixAreaY; // 垂直居中
imageScale = 1.0 * scaleImgWidth / imgWidth;
} else {
scaleImgHeight = autoFixAreaHeight;
scaleImgWidth = (int) (1.0F * scaleImgHeight * imgWidth / imgHeight);
scaleImgX = (autoFixAreaWidth - scaleImgWidth) / 2 + autoFixAreaX; // 水平居中
scaleImgY = autoFixAreaY;
imageScale = 1.0 * scaleImgHeight / imgHeight;
}
g2d.setColor(BACKGROUND_IMG_COLOR);
g2d.fillRect(scaleImgX, scaleImgY, scaleImgWidth, scaleImgHeight);
g2d.drawImage(image, scaleImgX, scaleImgY, scaleImgWidth, scaleImgHeight, null);
int scaleLeft = (int) (ninePointLeft * imageScale);
int scaleTop = (int) (ninePointTop * imageScale);
int scaleRight = (int) (ninePointRight * imageScale);
int scaleBottom = (int) (ninePointBottom * imageScale);
double topYInPane = scaleImgY + scaleTop;
double bottomYInPane = scaleImgY + scaleImgHeight - scaleBottom;
double leftXInPane = scaleImgX + scaleLeft;
double rightXInPane = scaleImgX + scaleImgWidth - scaleRight;
// 顶部分割线
drawDivider(g2d, scaleImgX, topYInPane, scaleImgX + scaleImgWidth, topYInPane, draggingTopDivider);
if (draggingTopDivider) {
// 顶部提示
drawHint(g2d, ninePointTop + "px", leftXInPane, scaleImgY, scaleImgWidth - scaleLeft - scaleRight, scaleTop, false);
}
// 底部分割线
drawDivider(g2d, scaleImgX, bottomYInPane, scaleImgX + scaleImgWidth, bottomYInPane, draggingBottomDivider);
if (draggingBottomDivider) {
// 底部提示
drawHint(g2d, ninePointBottom + "px", leftXInPane, bottomYInPane, scaleImgWidth - scaleLeft - scaleRight, scaleBottom, false);
}
// 左侧分割线
drawDivider(g2d, leftXInPane, scaleImgY, leftXInPane, scaleImgY + scaleImgHeight, draggingLeftDivider);
if (draggingLeftDivider) {
// 左侧提示
drawHint(g2d, ninePointLeft + "px", scaleImgX, topYInPane, scaleLeft, scaleImgHeight - scaleTop - scaleBottom, true);
}
// 右侧分割线
drawDivider(g2d, rightXInPane, scaleImgY, rightXInPane, scaleImgY + scaleImgHeight, draggingRightDivider);
if (draggingRightDivider) {
// 右侧提示
drawHint(g2d, ninePointRight + "px", rightXInPane, topYInPane, scaleRight, scaleImgHeight - scaleTop - scaleBottom, true);
}
}
private void drawHint(Graphics2D g2d, String hint, double x, double y, double width, double height, boolean horizontal) {
FontMetrics metrics = GraphDrawHelper.getFontMetrics(g2d.getFont());
double hintTextHeight = Math.max(metrics.getAscent() + metrics.getDescent(), 16);
double hintTextWidth = Math.max(metrics.stringWidth(hint), metrics.stringWidth("123"));
double hintFrameRadius = hintTextHeight / 2;
double hintFrameHeight = hintTextHeight;
double hintFrameWidth = hintTextWidth + 2 * hintFrameRadius;
double centerX = x + width / 2;
double centerY = y + height / 2;
double indent = 1.0;
double shortLine = 4.0;
if (horizontal) {
if (width > hintFrameWidth) {
g2d.setColor(HINT_BACKGROUND_COLOR);
GraphDrawHelper.draw(g2d, new Line2D.Double(x + indent, centerY, x + width - indent, centerY), Constants.LINE_THIN, 1.0F);
GraphDrawHelper.draw(g2d, new Line2D.Double(x + indent, centerY - shortLine, x + indent, centerY + shortLine), Constants.LINE_THIN, 1.0F);
GraphDrawHelper.draw(g2d, new Line2D.Double(x + width - indent, centerY - shortLine, x + width - indent, centerY + shortLine), Constants.LINE_THIN, 1.0F);
}
double hintFrameX = centerX - hintFrameWidth / 2;
double hintFrameY = centerY + HINT_GAP;
g2d.setColor(HINT_BACKGROUND_COLOR);
GraphDrawHelper.fill(g2d, new RoundRectangle2D.Double(hintFrameX, hintFrameY, hintFrameWidth, hintFrameHeight, hintFrameRadius * 2, hintFrameRadius * 2));
g2d.setColor(HINT_FOREGROUND_COLOR);
GraphDrawHelper.drawString(g2d, hint, hintFrameX + (hintFrameWidth - hintTextWidth) / 2, hintFrameY + (hintFrameHeight + hintTextHeight) / 2.0 - metrics.getDescent());
} else {
if (height > hintFrameHeight) {
g2d.setColor(HINT_BACKGROUND_COLOR);
GraphDrawHelper.draw(g2d, new Line2D.Double(centerX, y + indent, centerX, y + height - indent), Constants.LINE_THIN, 1.0F);
GraphDrawHelper.draw(g2d, new Line2D.Double(centerX - shortLine, y + indent, centerX + shortLine, y + indent), Constants.LINE_THIN, 1.0F);
GraphDrawHelper.draw(g2d, new Line2D.Double(centerX - shortLine, y + height - indent, centerX + shortLine, y + height - indent), Constants.LINE_THIN, 1.0F);
}
double hintFrameX = centerX + HINT_GAP;
double hintFrameY = centerY - hintFrameHeight / 2;
g2d.setColor(HINT_BACKGROUND_COLOR);
GraphDrawHelper.fill(g2d, new RoundRectangle2D.Double(hintFrameX, hintFrameY, hintFrameWidth, hintFrameHeight, hintFrameRadius * 2, hintFrameRadius * 2));
g2d.setColor(HINT_FOREGROUND_COLOR);
GraphDrawHelper.drawString(g2d, hint, hintFrameX + (hintFrameWidth - hintTextWidth) / 2, hintFrameY + (hintFrameHeight + hintTextHeight) / 2.0 - metrics.getDescent());
}
}
private void drawDivider(Graphics2D g2d, double x1, double y1, double x2, double y2, boolean dragging) {
if (dragging) {
g2d.setColor(DIVIDER_BACKGROUND_COLOR);
GraphDrawHelper.draw(g2d, new Line2D.Double(x1, y1, x2, y2), Constants.LINE_THIN, 2.0F);
g2d.setColor(DIVIDER_FOREGROUND_COLOR);
GraphDrawHelper.draw(g2d, new Line2D.Double(x1, y1, x2, y2), Constants.LINE_THIN, 1.0F);
} else {
g2d.setColor(DIVIDER_BACKGROUND_COLOR);
GraphDrawHelper.draw(g2d, new Line2D.Double(x1, y1, x2, y2), Constants.LINE_DASH, 1.0F);
}
}
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Cursor cursor = getCursor();
if (cursor == W_DRAG_CURSOR || cursor == NW_DRAG_CURSOR || cursor == SW_DRAG_CURSOR) {
int nextLeft = (int) ((x - scaleImgX) / imageScale);
this.onNinePointLeftChanged(nextLeft);
} else if (cursor == E_DRAG_CURSOR || cursor == NE_DRAG_CURSOR || cursor == SE_DRAG_CURSOR) {
int nextRight = (int) ((scaleImgX + scaleImgWidth - x) / imageScale);
this.onNinePointRightChanged(nextRight);
}
if (cursor == N_DRAG_CURSOR || cursor == NE_DRAG_CURSOR || cursor == NW_DRAG_CURSOR) {
int nextTop = (int) ((y - scaleImgY) / imageScale);
this.onNinePointTopChanged(nextTop);
} else if (cursor == S_DRAG_CURSOR || cursor == SE_DRAG_CURSOR || cursor == SW_DRAG_CURSOR) {
int nextBottom = (int) ((scaleImgY + scaleImgHeight - y) / imageScale);
this.onNinePointBottomChanged(nextBottom);
}
}
@Override
public void mouseMoved(MouseEvent e) {
boolean needRepaint;
int x = e.getX();
int y = e.getY();
double scaleLeft = ninePointLeft * imageScale;
double scaleTop = ninePointTop * imageScale;
double scaleRight = ninePointRight * imageScale;
double scaleBottom = ninePointBottom * imageScale;
// determine cursor
Cursor cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
boolean hoveringLeftDivider = false;
boolean hoveringRightDivider = false;
boolean hoveringTopDivider = false;
boolean hoveringBottomDivider = false;
if (scaleImgX - 2 <= x && x <= scaleImgX + scaleImgWidth + 2 && scaleImgY - 2 <= y && y <= scaleImgY + scaleImgHeight + 2) {
hoveringLeftDivider = Math.abs(x - (scaleImgX + scaleLeft)) < 2;
hoveringRightDivider = Math.abs(x - (scaleImgX + scaleImgWidth - scaleRight)) < 2;
hoveringTopDivider = Math.abs(y - (scaleImgY + scaleTop)) < 2;
hoveringBottomDivider = Math.abs(y - (scaleImgY + scaleImgHeight - scaleBottom)) < 2;
}
if (hoveringLeftDivider && hoveringTopDivider) {
cursor = NW_DRAG_CURSOR;
} else if (hoveringLeftDivider && hoveringBottomDivider) {
cursor = SW_DRAG_CURSOR;
} else if (hoveringRightDivider && hoveringTopDivider) {
cursor = NE_DRAG_CURSOR;
} else if (hoveringRightDivider && hoveringBottomDivider) {
cursor = SE_DRAG_CURSOR;
} else if (hoveringLeftDivider) {
cursor = W_DRAG_CURSOR;
} else if (hoveringRightDivider) {
cursor = E_DRAG_CURSOR;
} else if (hoveringTopDivider) {
cursor = N_DRAG_CURSOR;
} else if (hoveringBottomDivider) {
cursor = S_DRAG_CURSOR;
}
draggingLeftDivider = hoveringLeftDivider;
draggingRightDivider = hoveringRightDivider;
draggingTopDivider = hoveringTopDivider;
draggingBottomDivider = hoveringBottomDivider;
needRepaint = getCursor() != cursor;
this.setCursor(cursor);
if (needRepaint) {
repaint();
}
}
@Override
public void mouseClicked(MouseEvent e) {
requestFocus();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
this.draggingLeftDivider = false;
this.draggingRightDivider = false;
this.draggingTopDivider = false;
this.draggingBottomDivider = false;
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private void onNinePointTopChanged(int value) {
if (value < MIN_NINE_POINT) {
value = MIN_NINE_POINT;
} else if (value >= imgHeight - ninePointBottom) {
value = imgHeight - ninePointBottom - MIN_NINE_POINT;
}
this.ninePointTop = value;
repaint();
}
private void onNinePointBottomChanged(int value) {
if (value < MIN_NINE_POINT) {
value = MIN_NINE_POINT;
} else if (value >= imgHeight - ninePointTop) {
value = imgHeight - ninePointTop - MIN_NINE_POINT;
}
this.ninePointBottom = value;
repaint();
}
private void onNinePointLeftChanged(int value) {
if (value < MIN_NINE_POINT) {
value = MIN_NINE_POINT;
} else if (value >= imgWidth - ninePointRight) {
value = imgWidth - ninePointRight - MIN_NINE_POINT;
}
this.ninePointLeft = value;
repaint();
}
private void onNinePointRightChanged(int value) {
if (value < MIN_NINE_POINT) {
value = MIN_NINE_POINT;
} else if (value >= imgWidth - ninePointLeft) {
value = imgWidth - ninePointLeft - MIN_NINE_POINT;
}
this.ninePointRight = value;
repaint();
}
public void setNinePoint(int[] ninePoint) {
ninePointLeft = ninePoint[0];
ninePointTop = ninePoint[1];
ninePointRight = ninePoint[2];
ninePointBottom = ninePoint[3];
}
public int[] getNinePoint() {
return new int[] { ninePointLeft, ninePointTop, ninePointRight, ninePointBottom };
}
}
}