1. 设计器组件样式设置直接在设计器右侧栏展示 2. 设计器组件标题样式支持背景图片,图文混排 3. 设计器组件样式主体样式支持边框图片(点九图) 4. 标题样式背景填充,边框图片,主体背景填充支持透明度feature/10.0
@ -0,0 +1,30 @@
|
||||
package com.fr.design.gui.frpane; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/7/3 |
||||
*/ |
||||
public class UIPercentDragPane extends JPanel { |
||||
|
||||
private final UINumberDragPane dragPane = new UINumberDragPane(0, 100, 1); |
||||
|
||||
public UIPercentDragPane() { |
||||
setLayout(new BorderLayout()); |
||||
add(dragPane, BorderLayout.CENTER); |
||||
add(new UILabel(" %"), BorderLayout.EAST); |
||||
} |
||||
|
||||
public void populateBean(double value) { |
||||
dragPane.populateBean(value * 100); |
||||
} |
||||
|
||||
public double updateBean() { |
||||
return dragPane.updateBean() * 100; |
||||
} |
||||
} |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 280 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 155 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,598 @@
|
||||
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.gui.itooltip.UIToolTip; |
||||
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.form.ui.LayoutBorderStyle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.Constants; |
||||
import com.fr.stable.GraphDrawHelper; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import javax.swing.plaf.basic.BasicButtonUI; |
||||
import java.awt.*; |
||||
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.RoundRectangle2D; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
|
||||
/** |
||||
* @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 = 60; |
||||
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); |
||||
private final String TWEAK_NINE_POINT_HELP_URL = ""; |
||||
|
||||
private UIObserverListener uiObserverListener; |
||||
|
||||
private BorderLineAndImageComboBox borderLineCombo; |
||||
private UIColorButton borderColorPane; |
||||
private ImagePreviewPane imagePreviewPane; |
||||
private UIButton chooseImageButton; |
||||
private UIButton tweakNinePointHelpButton; |
||||
private UIButton tweakNinePointButton; |
||||
private UIPercentDragPane borderImageOpacityPane; |
||||
|
||||
private NinePointImageTweakDialogPane tweakPane; |
||||
private ImageFileChooser imageFileChooser; |
||||
|
||||
private int ninePointLeft = -1; |
||||
private int ninePointTop = -1; |
||||
private int ninePointRight = -1; |
||||
private int ninePointBottom = -1; |
||||
|
||||
public BorderLineAndImagePane() { |
||||
this.initComponents(); |
||||
this.initLayout(); |
||||
} |
||||
|
||||
private void initComponents() { |
||||
borderLineCombo = new BorderLineAndImageComboBox(); |
||||
borderColorPane = new UIColorButton(null) {{ |
||||
setUI(createButtonUI(this)); |
||||
set4ToolbarButton(); |
||||
}}; |
||||
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(TWEAK_NINE_POINT_HELP_URL)); |
||||
} 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}; |
||||
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); |
||||
} |
||||
} |
||||
|
||||
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.setColor(Color.BLACK); |
||||
} |
||||
if (!borderLineCombo.isSelectedBorderImage()) { |
||||
imagePreviewPane.setImageWithSuffix(null); |
||||
} |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
this.chooseImageButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initImageFileChooserIfNotExist(); |
||||
|
||||
int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); |
||||
ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, DEFAULT_IMAGE_LAYOUT_STYLE, new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
Image image = imagePreviewPane.getImage(); |
||||
ninePointLeft = ninePointRight = (image != null ? image.getWidth(null) / 3 : -1); |
||||
ninePointTop = ninePointBottom = (image != null ? image.getHeight(null) / 3 : -1); |
||||
borderImageOpacityPane.populateBean(1.0); |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}).dealWithImageFile(returnVal); |
||||
} |
||||
}); |
||||
this.tweakNinePointButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initNinePointTweakPaneIfNotExist(); |
||||
|
||||
if (imagePreviewPane.getImage() != null) { |
||||
BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(BorderLineAndImagePane.this)); |
||||
dialog.addDialogActionListener(new DialogActionAdapter() { |
||||
@Override |
||||
public void doOk() { |
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
dialog.setVisible(true); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void populateBean(LayoutBorderStyle style) { |
||||
int borderLine = style.getBorder(); |
||||
Color borderColor = style.getColor(); |
||||
|
||||
this.borderLineCombo.setSelectedLineStyle(borderLine); |
||||
this.borderColorPane.setColor(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.borderImageOpacityPane.populateBean(style.getBorderImageOpacity()); |
||||
if (ninePoint != null && ninePoint.length == 4 && ninePoint[0] > 0 && ninePoint[1] > 0 && ninePoint[2] > 0 && ninePoint[3] > 0) { |
||||
ninePointLeft = ninePoint[0]; |
||||
ninePointTop = ninePoint[1]; |
||||
ninePointRight = ninePoint[2]; |
||||
ninePointBottom = ninePoint[3]; |
||||
} else { |
||||
ninePointLeft = ninePointRight = image.getWidth(null) / 3; |
||||
ninePointTop = ninePointBottom = 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.setColor(style.getColor()); |
||||
} |
||||
|
||||
public void updateBean(LayoutBorderStyle style) { |
||||
|
||||
style.setBorder(this.borderLineCombo.getSelectedLineStyle()); |
||||
style.setColor(this.borderColorPane.getColor()); |
||||
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(new int[] { ninePointLeft, ninePointTop, ninePointRight, ninePointBottom }); |
||||
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_STYLE_ARRAY = new int[] { |
||||
Constants.LINE_NONE, |
||||
LINE_PICTURE, |
||||
Constants.LINE_THIN, //1px
|
||||
Constants.LINE_MEDIUM, //2px
|
||||
Constants.LINE_THICK, //3px
|
||||
}; |
||||
|
||||
public BorderLineAndImageComboBox() { |
||||
super(BORDER_LINE_STYLE_ARRAY); |
||||
} |
||||
|
||||
@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() { |
||||
return getSelectedIndex() > 1; |
||||
} |
||||
|
||||
public boolean isSelectedBorderImage() { |
||||
return getSelectedIndex() == 1; |
||||
} |
||||
|
||||
public void selectBorderImage() { |
||||
this.setSelectedIndex(1); |
||||
} |
||||
} |
||||
|
||||
private class NinePointImageTweakDialogPane extends BasicPane { |
||||
private final NinePointLinePreviewPane previewPane = new NinePointLinePreviewPane(); |
||||
|
||||
public NinePointImageTweakDialogPane() { |
||||
this.initComponents(); |
||||
} |
||||
|
||||
private void initComponents() { |
||||
setLayout(new BorderLayout()); |
||||
setBorder(BorderFactory.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill_Preview"))); |
||||
|
||||
JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
content.setBorder(BorderFactory.createEmptyBorder( |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1)); |
||||
content.add(previewPane); |
||||
previewPane.setPreferredSize(new Dimension(611, 457)); |
||||
|
||||
add(content, BorderLayout.CENTER); |
||||
} |
||||
|
||||
@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 { |
||||
private final BufferedImage transparentImage = IOUtils.readImage("/com/fr/design/images/transparent_background.jpg"); |
||||
|
||||
public final Color PATCH_COLOR = new Color(0, 0, 0, 38); |
||||
public final Color DIVIDER_COLOR = new Color(250, 250, 250); |
||||
public final Color TEXT_COLOR = Color.WHITE; |
||||
public final int PADDING = 15; |
||||
|
||||
private int imgWidth; |
||||
private int imgHeight; |
||||
private int scaleImgWidth; |
||||
private int scaleImgHeight; |
||||
private int scaleImgX; |
||||
private int scaleImgY; |
||||
private double scale = 1.0; |
||||
|
||||
public NinePointLinePreviewPane() { |
||||
this.addMouseMotionListener(this); |
||||
this.addMouseListener(this); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
|
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.drawImage(transparentImage, 0, 0, getWidth(), getHeight(), null); |
||||
|
||||
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 / imgHeight > autoFixAreaWidth / autoFixAreaHeight) { |
||||
scaleImgWidth = autoFixAreaWidth; |
||||
scaleImgHeight = (int) (1.0F * scaleImgWidth * imgHeight / imgWidth); |
||||
scaleImgX = autoFixAreaX; |
||||
scaleImgY = (autoFixAreaHeight - scaleImgHeight) / 2 + autoFixAreaY; // 垂直居中
|
||||
scale = 1.0 * scaleImgWidth / imgWidth; |
||||
} else { |
||||
scaleImgHeight = autoFixAreaHeight; |
||||
scaleImgWidth = (int) (1.0F * scaleImgHeight * imgWidth / imgHeight); |
||||
scaleImgX = (autoFixAreaWidth - scaleImgWidth) / 2 + autoFixAreaX; // 水平居中
|
||||
scaleImgY = autoFixAreaY; |
||||
scale = 1.0 * scaleImgHeight / imgHeight; |
||||
} |
||||
|
||||
g2d.drawImage(image, scaleImgX, scaleImgY, scaleImgWidth, scaleImgHeight, null); |
||||
|
||||
int scaleLeft = (int) (ninePointLeft * scale); |
||||
int scaleTop = (int) (ninePointTop * scale); |
||||
int scaleRight = (int) (ninePointRight * scale); |
||||
int scaleBottom = (int) (ninePointBottom * scale); |
||||
|
||||
g2d.setColor(PATCH_COLOR); |
||||
// draw horizontal patch
|
||||
GraphDrawHelper.fillRect(g2d, 0, scaleImgY + scaleTop, getWidth(), scaleImgHeight - scaleTop - scaleBottom); |
||||
// draw vertical patch
|
||||
GraphDrawHelper.fillRect(g2d, scaleImgX + scaleLeft, 0,scaleImgWidth - scaleLeft - scaleRight, getHeight()); |
||||
|
||||
g2d.setColor(DIVIDER_COLOR); |
||||
// draw top divider
|
||||
GraphDrawHelper.drawLine(g2d, 0, scaleImgY + scaleTop, getWidth(), scaleImgY + scaleTop); |
||||
// draw bottom divider
|
||||
GraphDrawHelper.drawLine(g2d, 0, scaleImgY + scaleImgHeight - scaleBottom, getWidth(), scaleImgY + scaleImgHeight - scaleBottom); |
||||
// draw left divider
|
||||
GraphDrawHelper.drawLine(g2d, scaleImgX + scaleLeft, 0, scaleImgX + scaleLeft, getHeight()); |
||||
// draw right divider
|
||||
GraphDrawHelper.drawLine(g2d, scaleImgX + scaleImgWidth - scaleRight, 0, scaleImgX + scaleImgWidth - scaleRight, getHeight()); |
||||
|
||||
g2d.setColor(TEXT_COLOR); |
||||
// draw nine point info
|
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointTop), scaleImgX + (scaleImgWidth + scaleLeft - scaleRight) / 2.0, (scaleImgY + scaleTop) / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointBottom), scaleImgX + scaleLeft + (scaleImgWidth - scaleLeft - scaleRight) / 2.0, scaleImgY + scaleImgHeight - (scaleBottom - PADDING) / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointLeft), (scaleImgX + scaleLeft) / 2.0, scaleImgY + (scaleImgHeight + scaleTop - scaleBottom) / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointRight), scaleImgX + scaleImgWidth - (scaleRight - PADDING) / 2.0, scaleImgY + (scaleImgHeight + scaleTop - scaleBottom) / 2.0); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseDragged(MouseEvent e) { |
||||
int x = e.getX(); |
||||
int y = e.getY(); |
||||
|
||||
int cursorType = getCursor().getType(); |
||||
|
||||
switch (cursorType) { |
||||
case Cursor.W_RESIZE_CURSOR: { |
||||
int nextLeft = (int) ((x - scaleImgX) / scale); |
||||
if (1 <= nextLeft && nextLeft < imgWidth - ninePointRight) { |
||||
ninePointLeft = nextLeft; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.E_RESIZE_CURSOR: { |
||||
int nextRight = (int) ((scaleImgX + scaleImgWidth - x) / scale); |
||||
if (1 <= nextRight && nextRight < imgWidth - ninePointLeft) { |
||||
ninePointRight = nextRight; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.N_RESIZE_CURSOR: { |
||||
int nextTop = (int) ((y - scaleImgY) / scale); |
||||
if (1 <= nextTop && nextTop < imgHeight - ninePointBottom) { |
||||
ninePointTop = nextTop; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.S_RESIZE_CURSOR: { |
||||
int nextBottom = (int) ((scaleImgY + scaleImgHeight - y) / scale); |
||||
if (1 <= nextBottom && nextBottom < imgHeight - ninePointTop) { |
||||
ninePointBottom = nextBottom; |
||||
repaint(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseMoved(MouseEvent e) { |
||||
boolean needRepaint; |
||||
|
||||
int x = e.getX(); |
||||
int y = e.getY(); |
||||
|
||||
double scaleLeft = ninePointLeft * scale; |
||||
double scaleTop = ninePointTop * scale; |
||||
double scaleRight = ninePointRight * scale; |
||||
double scaleBottom = ninePointBottom * scale; |
||||
|
||||
// determine cursor
|
||||
int cursorType = Cursor.DEFAULT_CURSOR; |
||||
|
||||
boolean hoveringLeftDivider = Math.abs(x - (scaleImgX + scaleLeft)) < 2; |
||||
boolean hoveringRightDivider = Math.abs(x - (scaleImgX + scaleImgWidth - scaleRight)) < 2; |
||||
boolean hoveringTopDivider = Math.abs(y - (scaleImgY + scaleTop)) < 2; |
||||
boolean hoveringBottomDivider = Math.abs(y - (scaleImgY + scaleImgHeight - scaleBottom)) < 2; |
||||
|
||||
if (hoveringLeftDivider) { |
||||
cursorType = Cursor.W_RESIZE_CURSOR; |
||||
} else if (hoveringRightDivider) { |
||||
cursorType = Cursor.E_RESIZE_CURSOR; |
||||
} else if (hoveringTopDivider) { |
||||
cursorType = Cursor.N_RESIZE_CURSOR; |
||||
} else if (hoveringBottomDivider) { |
||||
cursorType = Cursor.S_RESIZE_CURSOR; |
||||
} |
||||
|
||||
needRepaint = getCursor().getType() != cursorType; |
||||
this.setCursor(Cursor.getPredefinedCursor(cursorType)); |
||||
|
||||
if (needRepaint) { |
||||
repaint(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mouseReleased(MouseEvent e) { |
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
||||
|
||||
repaint(); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. |
||||
*/ |
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.form.ui.LayoutBorderStyle; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
/** |
||||
* CardTagLayoutBorderPane Pane. |
||||
*/ |
||||
public class CardTagLayoutStylePane extends LayoutStylePane { |
||||
|
||||
@Override |
||||
protected JPanel createTitleStylePane(){ |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void updateTitle(LayoutBorderStyle style) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
protected void populateTitle() { } |
||||
} |
@ -0,0 +1,502 @@
|
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.base.Utils; |
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.beans.BasicBeanPane; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.formula.TinyFormulaPane; |
||||
import com.fr.design.gui.frpane.UIPercentDragPane; |
||||
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||
import com.fr.design.gui.ibutton.UIColorButton; |
||||
import com.fr.design.gui.ibutton.UIToggleButton; |
||||
import com.fr.design.gui.icheckbox.UICheckBox; |
||||
import com.fr.design.gui.icombobox.LineComboBox; |
||||
import com.fr.design.gui.icombobox.UIComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.ispinner.UISpinner; |
||||
import com.fr.design.gui.style.BackgroundSpecialPane; |
||||
import com.fr.design.gui.style.FRFontPane; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.JForm; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.form.ui.LayoutBorderStyle; |
||||
import com.fr.form.ui.WidgetTitle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.general.act.TitlePacker; |
||||
import com.fr.stable.Constants; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.border.LineBorder; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/6/25 |
||||
* |
||||
* 可配置图片类型边框的样式设置面板 |
||||
*/ |
||||
public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> { |
||||
public static final String[] BORDER_STYLE = new String[]{ |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow") |
||||
}; |
||||
private static final Dimension BUTTON_SIZE = new Dimension(20, 20); |
||||
private static final int SETTING_LABEL_WIDTH = 60; |
||||
|
||||
protected LayoutBorderStyle style = new LayoutBorderStyle(); |
||||
|
||||
//渲染风格:有无阴影
|
||||
protected UIComboBox borderStyleCombo; |
||||
// 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色)
|
||||
protected BorderLineAndImagePane borderLineAndImagePane; |
||||
//边框圆角或圆角裁剪
|
||||
protected UISpinner cornerSpinner; |
||||
//主体背景
|
||||
protected BackgroundSpecialPane backgroundPane; |
||||
//主体背景透明度
|
||||
protected UIPercentDragPane backgroundOpacityPane; |
||||
|
||||
// 标题可见
|
||||
protected UICheckBox titleVisibleCheckbox; |
||||
//标题文字内容
|
||||
protected TinyFormulaPane titleTextPane; |
||||
//标题字体格式
|
||||
protected UIComboBox titleFontFamilyComboBox; |
||||
//标题字体大小
|
||||
protected UIComboBox titleFontSizeComboBox; |
||||
//标题字体颜色
|
||||
protected UIColorButton titleFontColorSelectPane; |
||||
//标题字体特殊效果:粗体、斜体、下划线
|
||||
private UIToggleButton titleFontBoldButton; |
||||
private UIToggleButton titleFontItalicButton; |
||||
private UIToggleButton titleFontUnderlineButton; |
||||
private LineComboBox titleFontUnderlineCombo; |
||||
// 标题图文混排
|
||||
protected TitleInsetImagePane titleInsetImagePane; |
||||
//对齐方式
|
||||
protected UIButtonGroup titleAlignPane; |
||||
//标题整体背景
|
||||
protected BackgroundSpecialPane titleBackgroundPane; |
||||
//标题背景透明度
|
||||
protected UIPercentDragPane titleBackgroundOpacityPane; |
||||
|
||||
public LayoutStylePane() { |
||||
this.initLayout(); |
||||
} |
||||
|
||||
protected void initLayout() { |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
|
||||
JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
boolean currentIsRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane(); |
||||
|
||||
JPanel titlePane = createTitleStylePane(); |
||||
if (titlePane != null) { |
||||
container.add(titlePane, BorderLayout.NORTH); |
||||
if (currentIsRootLayout) { |
||||
titlePane.setVisible(false); |
||||
} |
||||
} |
||||
|
||||
//界面上表单主体只有背景和透明度可以设置
|
||||
JPanel mainStylePane = currentIsRootLayout ? createMainStylePane4RootLayout() : createMainStylePane4WidgetLayout(); |
||||
if (mainStylePane != null) { |
||||
container.add(mainStylePane, BorderLayout.CENTER); |
||||
} |
||||
|
||||
this.add(container, BorderLayout.CENTER); |
||||
} |
||||
|
||||
protected void initMainComponents() { |
||||
borderStyleCombo = new UIComboBox(BORDER_STYLE); |
||||
borderLineAndImagePane = new BorderLineAndImagePane(); |
||||
cornerSpinner = new UISpinner(0,1000,1,0); |
||||
backgroundPane = new BackgroundSpecialPane(); |
||||
backgroundOpacityPane = new UIPercentDragPane(); |
||||
} |
||||
|
||||
protected JPanel createMainStylePane4WidgetLayout() { |
||||
initMainComponents(); |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p, p, p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame_Style")), null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), borderStyleCombo}, |
||||
{this.borderLineAndImagePane, null}, |
||||
{this.createMainBackgroundAndOpacityPane(), null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(contentPane, BorderLayout.NORTH); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createMainStylePane4RootLayout() { |
||||
initMainComponents(); |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame_Style")), null}, |
||||
{this.createMainBackgroundAndOpacityPane(), null}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(contentPane, BorderLayout.NORTH); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createMainBackgroundAndOpacityPane() { |
||||
return createBackgroundAndOpacityPane( |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Background"), |
||||
this.backgroundPane, |
||||
this.backgroundOpacityPane); |
||||
} |
||||
|
||||
protected void initTitleComponents() { |
||||
titleVisibleCheckbox = new UICheckBox(); |
||||
|
||||
titleTextPane = new TinyFormulaPane(); |
||||
|
||||
titleFontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); |
||||
titleFontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); |
||||
|
||||
titleFontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); |
||||
titleFontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); |
||||
|
||||
titleFontColorSelectPane = new UIColorButton(); |
||||
titleFontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||
titleFontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||
|
||||
titleFontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); |
||||
titleFontBoldButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||
titleFontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||
|
||||
titleFontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); |
||||
titleFontItalicButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||
titleFontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||
|
||||
titleFontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); |
||||
titleFontUnderlineButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||
titleFontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||
|
||||
titleFontUnderlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY); |
||||
titleFontUnderlineCombo.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Line_Style")); |
||||
|
||||
titleInsetImagePane = new TitleInsetImagePane(); |
||||
|
||||
titleAlignPane = new UIButtonGroup<Integer>( |
||||
new Icon[] { |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") |
||||
}, |
||||
new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); |
||||
titleAlignPane.setAllToolTips( |
||||
new String[] { |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right") |
||||
}); |
||||
|
||||
titleBackgroundPane = new BackgroundSpecialPane(); |
||||
|
||||
titleBackgroundOpacityPane = new UIPercentDragPane(); |
||||
} |
||||
|
||||
protected JPanel createTitleStylePane() { |
||||
initTitleComponents(); |
||||
|
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p,p,p,p,p,p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
final JPanel bottomPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), titleTextPane}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), titleFontFamilyComboBox}, |
||||
{null, createTitleFontButtonPane()}, |
||||
{titleInsetImagePane, null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane}, |
||||
{this.createTitleBackgroundAndOpacityPane(), null}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
bottomPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
bottomPane.setVisible(false); |
||||
|
||||
JPanel visibleComposedPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
|
||||
titleVisibleCheckbox.setSelected(false); |
||||
visibleComposedPane.add(titleVisibleCheckbox, BorderLayout.WEST); |
||||
visibleComposedPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); |
||||
|
||||
JPanel topPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title")), null}, |
||||
{visibleComposedPane, null} |
||||
}, new double[]{p, p}, new double[]{SETTING_LABEL_WIDTH, p}, IntervalConstants.INTERVAL_L1); |
||||
topPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(topPane, BorderLayout.NORTH); |
||||
container.add(bottomPane, BorderLayout.CENTER); |
||||
|
||||
titleVisibleCheckbox.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
bottomPane.setVisible(titleVisibleCheckbox.isSelected()); |
||||
} |
||||
}); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createTitleFontButtonPane(){ |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {f, p, p, p, p}; |
||||
|
||||
JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { |
||||
{titleFontSizeComboBox, titleFontColorSelectPane, titleFontItalicButton, titleFontBoldButton, titleFontUnderlineButton}, |
||||
}, rowSize, columnSize, IntervalConstants.INTERVAL_W0); |
||||
|
||||
JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
containerPane.add(buttonPane, BorderLayout.NORTH); |
||||
containerPane.add(titleFontUnderlineCombo, BorderLayout.CENTER); |
||||
|
||||
titleFontUnderlineCombo.setVisible(false); |
||||
titleFontUnderlineButton.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
titleFontUnderlineCombo.setVisible(titleFontUnderlineButton.isSelected()); |
||||
} |
||||
}); |
||||
|
||||
return containerPane; |
||||
} |
||||
|
||||
protected JPanel createTitleBackgroundAndOpacityPane() { |
||||
return createBackgroundAndOpacityPane( |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background"), |
||||
titleBackgroundPane, |
||||
titleBackgroundOpacityPane); |
||||
} |
||||
|
||||
@Override |
||||
public LayoutBorderStyle updateBean() { |
||||
LayoutBorderStyle style = new LayoutBorderStyle(); |
||||
updateMain(style); |
||||
updateTitle(style); |
||||
return style; |
||||
} |
||||
|
||||
protected void updateMain(LayoutBorderStyle style) { |
||||
if (borderStyleCombo != null) { |
||||
style.setBorderStyle(borderStyleCombo.getSelectedIndex()); |
||||
} |
||||
if (cornerSpinner != null) { |
||||
style.setBorderRadius((int) cornerSpinner.getValue()); |
||||
} |
||||
if (borderLineAndImagePane != null) { |
||||
borderLineAndImagePane.updateBean(style); |
||||
} |
||||
if (backgroundPane != null) { |
||||
style.setBackground(backgroundPane.update()); |
||||
} |
||||
if (backgroundOpacityPane != null) { |
||||
style.setAlpha((float)backgroundOpacityPane.updateBean()); |
||||
} |
||||
} |
||||
|
||||
protected void updateTitle(LayoutBorderStyle style) { |
||||
style.setType(titleVisibleCheckbox != null && titleVisibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); |
||||
TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); |
||||
title.setTextObject(titleTextPane.updateBean()); |
||||
FRFont frFont = title.getFrFont(); |
||||
frFont = frFont.applySize((Integer) titleFontSizeComboBox.getSelectedItem()); |
||||
frFont = frFont.applyName(titleFontFamilyComboBox.getSelectedItem().toString()); |
||||
frFont = frFont.applyForeground(titleFontColorSelectPane.getColor()); |
||||
frFont = updateTitleFontItalicBold(frFont); |
||||
int line = titleFontUnderlineButton.isSelected() ? this.titleFontUnderlineCombo.getSelectedLineStyle() : Constants.LINE_NONE; |
||||
frFont = frFont.applyUnderline(line); |
||||
title.setFrFont(frFont); |
||||
title.setPosition((Integer) titleAlignPane.getSelectedItem()); |
||||
titleInsetImagePane.updateBean(title); |
||||
title.setBackground(titleBackgroundPane.update()); |
||||
title.setBackgroundOpacity((float)titleBackgroundOpacityPane.updateBean()); |
||||
style.setTitle(title); |
||||
} |
||||
|
||||
private FRFont updateTitleFontItalicBold(FRFont frFont) { |
||||
int italic_bold = frFont.getStyle(); |
||||
boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); |
||||
boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); |
||||
if (titleFontItalicButton.isSelected() && !isItalic) { |
||||
italic_bold += Font.ITALIC; |
||||
} else if (!titleFontItalicButton.isSelected() && isItalic) { |
||||
italic_bold -= Font.ITALIC; |
||||
} |
||||
frFont = frFont.applyStyle(italic_bold); |
||||
if (titleFontBoldButton.isSelected() && !isBold) { |
||||
italic_bold += Font.BOLD; |
||||
} else if (!titleFontBoldButton.isSelected() && isBold) { |
||||
italic_bold -= Font.BOLD; |
||||
} |
||||
frFont = frFont.applyStyle(italic_bold); |
||||
return frFont; |
||||
} |
||||
|
||||
@Override |
||||
public void populateBean(LayoutBorderStyle style) { |
||||
if(this.style == null) { |
||||
this.style = new LayoutBorderStyle(); |
||||
} |
||||
this.style.setStyle(style); |
||||
|
||||
populateMain(); |
||||
populateTitle(); |
||||
} |
||||
|
||||
protected void populateMain() { |
||||
if (this.borderStyleCombo != null) { |
||||
this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); |
||||
} |
||||
if (this.borderLineAndImagePane != null) { |
||||
this.borderLineAndImagePane.populateBean(style); |
||||
} |
||||
if (this.backgroundPane != null) { |
||||
this.backgroundPane.populateBean(style.getBackground()); |
||||
if (this.backgroundOpacityPane != null) { |
||||
this.backgroundOpacityPane.populateBean(style.getAlpha()); |
||||
} |
||||
} |
||||
if (this.cornerSpinner != null) { |
||||
this.cornerSpinner.setValue(style.getBorderRadius()); |
||||
} |
||||
} |
||||
|
||||
protected void populateTitle() { |
||||
TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); |
||||
widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; |
||||
titleVisibleCheckbox.setSelected(style.getType() != LayoutBorderStyle.STANDARD); |
||||
|
||||
this.titleTextPane.populateBean(widgetTitle.getTextObject().toString()); |
||||
|
||||
FRFont frFont = widgetTitle.getFrFont(); |
||||
this.titleFontSizeComboBox.setSelectedItem(frFont.getSize()); |
||||
this.titleFontFamilyComboBox.setSelectedItem(frFont.getFamily()); |
||||
this.titleFontColorSelectPane.setColor(frFont.getForeground()); |
||||
this.titleFontColorSelectPane.repaint(); |
||||
titleFontBoldButton.setSelected(frFont.isBold()); |
||||
titleFontItalicButton.setSelected(frFont.isItalic()); |
||||
|
||||
int line = frFont.getUnderline(); |
||||
if (line == Constants.LINE_NONE) { |
||||
titleFontUnderlineButton.setSelected(false); |
||||
titleFontUnderlineCombo.setVisible(false); |
||||
} else { |
||||
titleFontUnderlineButton.setSelected(true); |
||||
titleFontUnderlineCombo.setVisible(true); |
||||
this.titleFontUnderlineCombo.setSelectedLineStyle(line); |
||||
} |
||||
|
||||
titleAlignPane.setSelectedItem(widgetTitle.getPosition()); |
||||
titleInsetImagePane.populateBean(widgetTitle); |
||||
titleBackgroundPane.populateBean(widgetTitle.getBackground()); |
||||
titleBackgroundOpacityPane.populateBean(widgetTitle.getBackgroundOpacity()); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style"); |
||||
} |
||||
|
||||
private static JPanel createBackgroundAndOpacityPane(String name, BackgroundSpecialPane backgroundPane, UIPercentDragPane opacityPane) { |
||||
JPanel container = new JPanel(); |
||||
container.setLayout(new BorderLayout(0, 6)); |
||||
|
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
// 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐
|
||||
JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||
backgroundLabelPane.add(new UILabel(name), BorderLayout.NORTH); |
||||
|
||||
JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{backgroundLabelPane, backgroundPane} |
||||
}, |
||||
new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
|
||||
JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, |
||||
{new UILabel(""), opacityPane} |
||||
}, |
||||
new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
|
||||
container.add(backgroundComposedPane, BorderLayout.NORTH, 0); |
||||
container.add(opacityComposedPane, BorderLayout.CENTER, 1); |
||||
|
||||
opacityComposedPane.setVisible(false); |
||||
|
||||
backgroundPane.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
Background background = backgroundPane.update(); |
||||
opacityComposedPane.setVisible(background != null); |
||||
} |
||||
}); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected static class BottomLineBorder extends LineBorder { |
||||
|
||||
public BottomLineBorder() { |
||||
super(Color.lightGray, 1); |
||||
} |
||||
|
||||
@Override |
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
Color oldColor = g2d.getColor(); |
||||
g2d.setColor(this.lineColor); |
||||
GraphHelper.drawLine(g, 0, height, width, height, 1); |
||||
g2d.setColor(oldColor); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,258 @@
|
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.base.Style; |
||||
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.event.UIObserver; |
||||
import com.fr.design.event.UIObserverListener; |
||||
import com.fr.design.gui.frpane.ImgChooseWrapper; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.ispinner.UISpinner; |
||||
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.widget.ui.designer.component.UIBoundSpinner; |
||||
import com.fr.form.ui.WidgetTitle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.general.ImageWithSuffix; |
||||
import com.fr.general.act.TitlePacker; |
||||
import com.fr.stable.Constants; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import javax.swing.plaf.basic.BasicButtonUI; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/7/3 |
||||
*/ |
||||
public class TitleInsetImagePane extends JPanel implements UIObserver { |
||||
private final int SETTING_LABEL_WIDTH = 60; |
||||
private final int DELETE_BUTTON_SIZE = 24; |
||||
private final int IMAGE_PREVIEW_SIZE = 145; |
||||
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); |
||||
private final int DEFAULT_INSET_LOCATION_INDEX = 0; |
||||
private final int DEFAULT_INSET_PADDING = 10; |
||||
|
||||
private UIObserverListener uiObserverListener; |
||||
|
||||
private UIButton imageChooseButton; |
||||
private UIButton imageDeleteButton; |
||||
private ImagePreviewPane imagePreviewPane; |
||||
private UIButtonGroup<Integer> imageLocationPane; |
||||
private UISpinner imagePaddingPane; |
||||
|
||||
private ImageFileChooser imageFileChooser; |
||||
|
||||
public TitleInsetImagePane() { |
||||
this.initComponents(); |
||||
this.initLayout(); |
||||
} |
||||
|
||||
private JPanel createImageChooseComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
return TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset")), this.imageChooseButton}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
} |
||||
|
||||
private JPanel createImageContentComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p, p, p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel deletableImagePreviewPane = new JPanel(); |
||||
deletableImagePreviewPane.setLayout(null); |
||||
deletableImagePreviewPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 5)); |
||||
deletableImagePreviewPane.setPreferredSize(new Dimension(IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE)); |
||||
imagePreviewPane.setBounds(0, 0, IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE); |
||||
imageDeleteButton.setBounds(IMAGE_PREVIEW_SIZE - DELETE_BUTTON_SIZE, 0, DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE); |
||||
deletableImagePreviewPane.add(imageDeleteButton, 0); |
||||
deletableImagePreviewPane.add(imagePreviewPane, 1); |
||||
|
||||
return TableLayoutHelper.createCommonTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{null, deletableImagePreviewPane}, |
||||
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Location"))}, |
||||
{null, this.imageLocationPane}, |
||||
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Padding"))}, |
||||
{null, this.imagePaddingPane} |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
} |
||||
|
||||
private void initImageFileChooserIfNotExist() { |
||||
if (imageFileChooser == null) { |
||||
imageFileChooser = new ImageFileChooser(); |
||||
imageFileChooser.setMultiSelectionEnabled(false); |
||||
} |
||||
} |
||||
|
||||
private void initComponents() { |
||||
imageChooseButton = new UIButton(IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_choose_inset.png")); |
||||
|
||||
imageDeleteButton = new UIButton(IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_delete_inset.png")); |
||||
imageDeleteButton.setUI(new BasicButtonUI()); |
||||
imageDeleteButton.setOpaque(true); |
||||
imageDeleteButton.setBorderPainted(false); |
||||
imageDeleteButton.setBorder(null); |
||||
imageDeleteButton.setFocusPainted(false); |
||||
imageDeleteButton.setContentAreaFilled(true); |
||||
imageDeleteButton.setPreferredSize(new Dimension(DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE)); |
||||
imageDeleteButton.setBackground(new Color(51, 51, 51)); |
||||
|
||||
imagePreviewPane = new ImagePreviewPane(); |
||||
imagePreviewPane.setImageStyle(DEFAULT_IMAGE_LAYOUT_STYLE); |
||||
imagePreviewPane.setPreferredSize(new Dimension(IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE)); |
||||
|
||||
imageLocationPane = new UIButtonGroup<Integer>(new Icon[][]{ |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_left_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_left_unselected.png") |
||||
}, |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_both_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_both_unselected.png") |
||||
}, |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_right_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_right_unselected.png") |
||||
}, |
||||
}); |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imageLocationPane.setAllToolTips(new String[]{ |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Left_Tooltip"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Both_Tooltip"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Right_Tooltip"), |
||||
}); |
||||
|
||||
imagePaddingPane = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
} |
||||
|
||||
private void initLayout() { |
||||
|
||||
|
||||
this.setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); |
||||
|
||||
add(createImageChooseComposedPane(), BorderLayout.NORTH, 0); |
||||
add(createImageContentComposedPane(), BorderLayout.CENTER, 1); |
||||
|
||||
getComponent(1).setVisible(false); |
||||
|
||||
this.imageChooseButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initImageFileChooserIfNotExist(); |
||||
|
||||
int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); |
||||
ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, DEFAULT_IMAGE_LAYOUT_STYLE, new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
if (!getComponent(1).isVisible()) { |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
getComponent(1).setVisible(true); |
||||
} |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}).dealWithImageFile(returnVal); |
||||
} |
||||
}); |
||||
this.imageDeleteButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
imagePreviewPane.setImageWithSuffix(null); |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
getComponent(1).setVisible(false); |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void populateBean(TitlePacker packer) { |
||||
Background insetImage = packer.getInsetImage(); |
||||
if (insetImage instanceof ImageBackground) { |
||||
ImageWithSuffix image = ((ImageBackground) insetImage).getImageWithSuffix(); |
||||
if (image != null) { |
||||
this.imagePreviewPane.setImageWithSuffix(image); |
||||
|
||||
if (!packer.isInsetRelativeTextLeft()) { |
||||
this.imageLocationPane.setSelectedIndex(2); |
||||
} else if (!packer.isInsetRelativeTextRight()) { |
||||
this.imageLocationPane.setSelectedIndex(0); |
||||
} else { |
||||
this.imageLocationPane.setSelectedIndex(1); |
||||
} |
||||
|
||||
this.imagePaddingPane.setValue(packer.getInsetImagePadding()); |
||||
|
||||
getComponent(1).setVisible(true); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
this.imagePreviewPane.setImageWithSuffix(null); |
||||
this.imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
this.imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
|
||||
getComponent(1).setVisible(false); |
||||
} |
||||
|
||||
public void updateBean(TitlePacker packer) { |
||||
Image image = imagePreviewPane.getImageWithSuffix(); |
||||
if (image != null) { |
||||
packer.setInsetImage(new ImageFileBackground(image, Constants.IMAGE_DEFAULT)); |
||||
|
||||
int imageLocationIndex = this.imageLocationPane.getSelectedIndex(); |
||||
packer.setInsetRelativeTextLeft(imageLocationIndex == 0 || imageLocationIndex == 1); |
||||
packer.setInsetRelativeTextRight(imageLocationIndex == 2 || imageLocationIndex == 1); |
||||
|
||||
packer.setInsetImagePadding((int) this.imagePaddingPane.getValue()); |
||||
} else { |
||||
packer.setInsetImage(null); |
||||
packer.setInsetImagePadding(WidgetTitle.DEFAULT_INSET_PADDING); |
||||
packer.setInsetRelativeTextLeft(WidgetTitle.DEFAULT_INSET_LEFT); |
||||
packer.setInsetRelativeTextRight(WidgetTitle.DEFAULT_INSET_RIGHT); |
||||
} |
||||
} |
||||
|
||||
private void fireStateChanged() { |
||||
if (uiObserverListener != null) { |
||||
uiObserverListener.doChange(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerChangeListener(UIObserverListener listener) { |
||||
this.uiObserverListener = listener; |
||||
} |
||||
|
||||
@Override |
||||
public boolean shouldResponseChangeListener() { |
||||
return true; |
||||
} |
||||
} |