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.
472 lines
19 KiB
472 lines
19 KiB
package com.fr.quickeditor; |
|
|
|
import com.fr.base.GraphHelper; |
|
import com.fr.base.Style; |
|
import com.fr.design.actions.UpdateAction; |
|
import com.fr.design.actions.core.ActionFactory; |
|
import com.fr.design.file.HistoryTemplateListCache; |
|
import com.fr.design.gui.frpane.AttributeChangeListener; |
|
import com.fr.design.gui.icombobox.UIComboBox; |
|
import com.fr.design.gui.ilable.UILabel; |
|
import com.fr.design.gui.iscrollbar.UIScrollBar; |
|
import com.fr.design.gui.itextfield.UITextField; |
|
import com.fr.design.gui.style.TextFormatPaneContainer; |
|
import com.fr.design.i18n.Toolkit; |
|
import com.fr.design.layout.TableLayout; |
|
import com.fr.design.layout.TableLayoutHelper; |
|
import com.fr.design.mainframe.CellElementPropertyPane; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.mainframe.ElementCasePane; |
|
import com.fr.design.mainframe.JTemplate; |
|
import com.fr.design.menu.MenuKeySet; |
|
import com.fr.design.menu.ShortCut; |
|
import com.fr.design.selection.QuickEditor; |
|
import com.fr.design.utils.gui.UIComponentUtils; |
|
import com.fr.design.widget.FRWidgetFactory; |
|
import com.fr.grid.selection.CellSelection; |
|
import com.fr.quickeditor.cellquick.layout.CellElementBarLayout; |
|
import com.fr.report.cell.TemplateCellElement; |
|
import com.fr.report.elementcase.TemplateElementCase; |
|
import com.fr.stable.ColumnRow; |
|
|
|
import javax.swing.BorderFactory; |
|
import javax.swing.JComponent; |
|
import javax.swing.JOptionPane; |
|
import javax.swing.JPanel; |
|
import javax.swing.JScrollBar; |
|
import javax.swing.SwingUtilities; |
|
import java.awt.BorderLayout; |
|
import java.awt.Component; |
|
import java.awt.Container; |
|
import java.awt.Dimension; |
|
import java.awt.event.ActionEvent; |
|
import java.awt.event.ActionListener; |
|
import java.awt.event.AdjustmentEvent; |
|
import java.awt.event.AdjustmentListener; |
|
import java.awt.event.MouseWheelEvent; |
|
import java.awt.event.MouseWheelListener; |
|
import java.text.Format; |
|
import java.util.ArrayList; |
|
import java.util.Objects; |
|
import java.util.Set; |
|
|
|
/** |
|
* @author zhou, yaoh.wu |
|
* @version 2017年8月7日16点54分 |
|
* @since 1.0 |
|
*/ |
|
public abstract class CellQuickEditor extends QuickEditor<ElementCasePane> { |
|
|
|
protected static final Dimension LABEL_DIMENSION = new Dimension(GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Report_Insert_Cell_Element")), 20); |
|
protected static final int VGAP = 10, HGAP = 8, VGAP_INNER = 3; |
|
|
|
/** |
|
* 滚动条相关配置 |
|
*/ |
|
private static final int MAXVALUE = 100; |
|
private static final int CONTENT_PANE_WIDTH_GAP = 3; |
|
private static final int MOUSE_WHEEL_SPEED = 5; |
|
private static final int SCROLLBAR_WIDTH = 7; |
|
private UILabel cellLabel; |
|
|
|
private int maxHeight = 280; |
|
private static final int TITLE_HEIGHT = 50; |
|
|
|
/** |
|
* 面板配置 |
|
*/ |
|
protected UITextField columnRowTextField; |
|
protected TemplateCellElement cellElement; |
|
private TextFormatPaneContainer formatPane; |
|
private JPanel topContentContainer; |
|
private JComponent centerBodyContainer; |
|
private UILabel multipleLabelTip; |
|
|
|
|
|
// 占位label |
|
protected final UILabel EMPTY_LABEL = new UILabel(); |
|
|
|
private UIComboBox comboBox; |
|
|
|
private UpdateAction[] cellInsertActions; |
|
private int selectedIndex; |
|
private int currentSelectedIndex; |
|
private JPanel leftContentPane; |
|
private UIScrollBar scrollBar; |
|
private ActionListener comboBoxActionListener; |
|
|
|
public CellQuickEditor() { |
|
|
|
initComponents(); |
|
|
|
createPanelBody(); |
|
} |
|
|
|
private void initComponents() { |
|
EMPTY_LABEL.setPreferredSize(LABEL_DIMENSION); |
|
topContentContainer = initTopContent(); |
|
formatPane = createFormatPane(); |
|
centerBodyContainer = createCenterBody(); |
|
|
|
multipleLabelTip = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Basic_Cell_Element_Multiple_Tip")); |
|
multipleLabelTip.setEnabled(false); |
|
} |
|
|
|
private void createPanelBody() { |
|
double p = TableLayout.PREFERRED; |
|
double f = TableLayout.FILL; |
|
double[] columnSize = {f}; |
|
if (isScrollAll()) { |
|
double[] scrollAllRowSize = {p, p, p, p}; |
|
prepareScrollBar(); |
|
multipleLabelTip.setBorder(BorderFactory.createMatteBorder(5, 10, 0, 0, this.getBackground())); |
|
topContentContainer.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 0, this.getBackground())); |
|
formatPane.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 0, this.getBackground())); |
|
centerBodyContainer.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 0, this.getBackground())); |
|
Component[][] components = new Component[][]{ |
|
new Component[]{multipleLabelTip}, |
|
new Component[]{topContentContainer}, |
|
new Component[]{formatPane}, |
|
new Component[]{centerBodyContainer} |
|
}; |
|
leftContentPane = TableLayoutHelper.createGapTableLayoutPane(components, scrollAllRowSize, columnSize, HGAP, VGAP); |
|
this.setLayout(new CellElementBarLayout(leftContentPane) { |
|
@Override |
|
public void layoutContainer(Container parent) { |
|
maxHeight = CellElementPropertyPane.getInstance().getHeight() - TITLE_HEIGHT; |
|
int beginY; |
|
if ((MAXVALUE - scrollBar.getVisibleAmount()) == 0) { |
|
beginY = 0; |
|
} else { |
|
int preferredHeight = leftContentPane.getPreferredSize().height; |
|
int value = scrollBar.getValue(); |
|
beginY = value * (preferredHeight - maxHeight) / (MAXVALUE - scrollBar.getVisibleAmount()); |
|
} |
|
int width = parent.getWidth(); |
|
int height = parent.getHeight(); |
|
if (leftContentPane.getPreferredSize().height > maxHeight) { |
|
leftContentPane.setBounds(0, -beginY, width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, height + beginY); |
|
scrollBar.setBounds(width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, 0, SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP, height); |
|
} else { |
|
leftContentPane.setBounds(0, 0, width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, height); |
|
} |
|
leftContentPane.validate(); |
|
} |
|
}); |
|
this.add(scrollBar); |
|
this.add(leftContentPane); |
|
} else { |
|
double[] scrollContentRowSize = {p, p, p, f}; |
|
multipleLabelTip.setBorder(BorderFactory.createMatteBorder(5, 10, 0, 0, this.getBackground())); |
|
topContentContainer.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 10, this.getBackground())); |
|
formatPane.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 10, this.getBackground())); |
|
centerBodyContainer.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, this.getBackground())); |
|
Component[][] components = new Component[][]{ |
|
new Component[]{multipleLabelTip}, |
|
new Component[]{topContentContainer}, |
|
new Component[]{formatPane}, |
|
new Component[]{centerBodyContainer} |
|
}; |
|
this.setLayout(new BorderLayout()); |
|
this.add(TableLayoutHelper.createGapTableLayoutPane(components, scrollContentRowSize, columnSize, HGAP, VGAP), BorderLayout.CENTER); |
|
} |
|
} |
|
|
|
/** |
|
* 初始化详细信息面板 |
|
* |
|
* @return JComponent 待显示的详细信息面板 |
|
*/ |
|
public abstract JComponent createCenterBody(); |
|
|
|
/** |
|
* 是否全局具有滚动条 |
|
* |
|
* @return boolean 是否全局具有滚动条 |
|
*/ |
|
public abstract boolean isScrollAll(); |
|
|
|
|
|
/** |
|
* 初始化下拉框中的类型 |
|
* |
|
* @return JComponent 待显示的详细信息面板 |
|
*/ |
|
public abstract Object getComboBoxSelected(); |
|
|
|
|
|
/** |
|
* 刷新 |
|
*/ |
|
@Override |
|
protected void refresh() { |
|
|
|
refreshPanel(); |
|
|
|
refreshFormatPanel(); |
|
|
|
refreshDetails(); |
|
|
|
refreshMultipleDetails(); |
|
} |
|
|
|
/** |
|
* 多选时默认隐藏与插入元素类型相关的所有面板 |
|
* 若其他面板需要扩展多选时可修改的内容, |
|
* 通过重写改方法,实现显示/隐藏部分组件 |
|
*/ |
|
public void refreshMultipleDetails() { |
|
centerBodyContainer.setVisible(tc.isSelectedOneCell()); |
|
} |
|
|
|
private void refreshFormatPanel() { |
|
// 在populate的时候会多次触发AttributeChangeListener事件, |
|
// 导致不断更新单元格格式,因此populate的时候暂时删除listener |
|
formatPane.removeAttributeChangeListener(); |
|
|
|
if (cellElement != null) { |
|
formatPane.populateBean(cellElement.getStyle()); |
|
} else { |
|
formatPane.populateBean(Style.DEFAULT_STYLE); |
|
} |
|
|
|
formatPane.restoreAttributeChangeListener(); |
|
} |
|
|
|
private void refreshPanel() { |
|
changeVisiableState(); |
|
|
|
CellSelection cs = (CellSelection) tc.getSelection(); |
|
ColumnRow columnRow = ColumnRow.valueOf(cs.getColumn(), cs.getRow()); |
|
|
|
columnRowTextField.setText(columnRow.toString()); |
|
cellElement = tc.getEditingElementCase().getTemplateCellElement(cs.getColumn(), cs.getRow()); |
|
|
|
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
|
if (jTemplate != null) { |
|
comboBox.removeActionListener(comboBoxActionListener); |
|
comboBox.removeAllItems(); |
|
String[] items = getDefaultComboBoxItems(); |
|
for (String item : items) { |
|
comboBox.addItem(item); |
|
} |
|
Object comboBoxSelected = getComboBoxSelected(); |
|
if (comboBoxSelected != null) { |
|
comboBox.setSelectedItem(((ShortCut) comboBoxSelected).getMenuKeySet().getMenuKeySetName()); |
|
} else { |
|
comboBox.setSelectedIndex(1); |
|
} |
|
currentSelectedIndex = comboBox.getSelectedIndex(); |
|
comboBoxActionListener = new ActionListener() { |
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
cellInsertActions = ActionFactory.createCellInsertAction(ElementCasePane.class, tc); |
|
selectedIndex = comboBox.getSelectedIndex(); |
|
comboBox.setPopupVisible(false); |
|
comboBox.repaint(); |
|
// comboBox.getSelectedIndex()可能返回-1 |
|
if (selectedIndex != -1 && selectedIndex < cellInsertActions.length) { |
|
cellInsertActions[selectedIndex].actionPerformed(e); |
|
} |
|
comboBox.setSelectedIndex(currentSelectedIndex); |
|
} |
|
}; |
|
comboBox.addActionListener(comboBoxActionListener); |
|
} |
|
} |
|
|
|
/** |
|
* 单选多选时切换部分组件的 隐藏/显示 状态 |
|
*/ |
|
private void changeVisiableState() { |
|
boolean selectedOneCell = tc.isSelectedOneCell(); |
|
|
|
comboBox.setEnabled(selectedOneCell); |
|
if (selectedOneCell) { |
|
columnRowTextField.setPreferredSize(null); |
|
cellLabel.setPreferredSize(null); |
|
multipleLabelTip.setPreferredSize(new Dimension()); |
|
} else { |
|
columnRowTextField.setPreferredSize(new Dimension()); |
|
cellLabel.setPreferredSize(new Dimension()); |
|
multipleLabelTip.setPreferredSize(null); |
|
} |
|
} |
|
|
|
/** |
|
* 刷新详细信息 |
|
*/ |
|
protected abstract void refreshDetails(); |
|
|
|
|
|
private JPanel initTopContent() { |
|
|
|
double p = TableLayout.PREFERRED; |
|
double f = TableLayout.FILL; |
|
double[] columnSize = {GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Report_Insert_Cell_Element")), f}; |
|
double[] rowSize = {p, p}; |
|
cellLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Basic_Cell")); |
|
UILabel insertContentLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Report_Insert_Cell_Element")); |
|
initCellElementEditComboBox(); |
|
Component[][] components = new Component[][]{ |
|
new Component[]{cellLabel, columnRowTextField = initColumnRowTextField()}, |
|
new Component[]{insertContentLabel, UIComponentUtils.wrapWithBorderLayoutPane(comboBox)}, |
|
}; |
|
return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, HGAP, VGAP); |
|
} |
|
|
|
private void prepareScrollBar() { |
|
scrollBar = new UIScrollBar(UIScrollBar.VERTICAL) { |
|
@Override |
|
public int getVisibleAmount() { |
|
int preferredHeight = leftContentPane.getPreferredSize().height; |
|
int e = MAXVALUE * (maxHeight) / preferredHeight; |
|
setVisibleAmount(e); |
|
return e; |
|
} |
|
|
|
@Override |
|
public int getMaximum() { |
|
return MAXVALUE; |
|
} |
|
}; |
|
|
|
scrollBar.addAdjustmentListener(new AdjustmentListener() { |
|
|
|
@Override |
|
public void adjustmentValueChanged(AdjustmentEvent e) { |
|
doLayout(); |
|
} |
|
}); |
|
this.addMouseWheelListener(new MouseWheelListener() { |
|
|
|
@Override |
|
public void mouseWheelMoved(MouseWheelEvent e) { |
|
int value = scrollBar.getValue(); |
|
value += MOUSE_WHEEL_SPEED * e.getWheelRotation(); |
|
scrollBar.setValue(value); |
|
doLayout(); |
|
} |
|
}); |
|
|
|
scrollBar.setPreferredSize(new Dimension(SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP, this.getHeight())); |
|
scrollBar.setBlockIncrement(SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP); |
|
scrollBar.setBorder(BorderFactory.createMatteBorder(0, CONTENT_PANE_WIDTH_GAP, 0, 0, this.getBackground())); |
|
} |
|
|
|
/** |
|
* 初始化添加按钮 |
|
*/ |
|
private void initCellElementEditComboBox() { |
|
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
|
if (jTemplate == null) { |
|
comboBox = new UIComboBox(); |
|
return; |
|
} |
|
final String[] items = getDefaultComboBoxItems(); |
|
comboBox = new UIComboBox(items); |
|
final Object comboBoxSelected = getComboBoxSelected(); |
|
if (comboBoxSelected != null) { |
|
comboBox.setSelectedItem(((ShortCut) comboBoxSelected).getMenuKeySet().getMenuKeySetName()); |
|
} else { |
|
comboBox.setSelectedIndex(1); |
|
} |
|
currentSelectedIndex = comboBox.getSelectedIndex(); |
|
comboBox.addActionListener(comboBoxActionListener); |
|
} |
|
|
|
private String[] getDefaultComboBoxItems() { |
|
MenuKeySet[] cellInsertActionNames = ActionFactory.createCellInsertActionName(); |
|
ArrayList<String> names = new ArrayList<>(); |
|
for (MenuKeySet cellInsertActionName : cellInsertActionNames) { |
|
names.add(cellInsertActionName.getMenuKeySetName()); |
|
} |
|
return names.toArray(new String[names.size()]); |
|
} |
|
|
|
/** |
|
* 初始化单元格域,存储当前选择的单元格,例A3,B4等 |
|
* |
|
* @return 单元格信息文本域 |
|
*/ |
|
private UITextField initColumnRowTextField() { |
|
final UITextField columnRowTextField = new UITextField(4); |
|
|
|
// barry:输入位置定位单元格 |
|
columnRowTextField.addActionListener(new ActionListener() { |
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
ColumnRow columnRowEdit = ColumnRow.valueOf(columnRowTextField.getText()); |
|
// barry:检查输入是否正确 |
|
if (!ColumnRow.validate(columnRowEdit)) { |
|
Object[] options = {Toolkit.i18nText("Fine-Design_Report_OK")}; |
|
JOptionPane.showOptionDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Please_Input_Letters+Numbers(A1,AA1,A11....)"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Warning"), |
|
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]); |
|
// 重新选中当前的selection,把columnRowTextField |
|
tc.setSelection(tc.getSelection()); |
|
return; |
|
} |
|
JScrollBar verticalBar = tc.getVerticalScrollBar(), horizontalBar = tc.getHorizontalScrollBar(); |
|
int m = columnRowEdit.getColumn(), n = columnRowEdit.getRow(); |
|
verticalBar.setMaximum(n); |
|
verticalBar.setValue(n < 21 ? verticalBar.getValue() : n - 20); |
|
horizontalBar.setMaximum(m); |
|
horizontalBar.setValue(m < 13 ? horizontalBar.getValue() : m - 12); |
|
tc.setSelection(new CellSelection(m, n, 1, 1)); |
|
tc.requestFocus(); |
|
} |
|
}); |
|
return columnRowTextField; |
|
} |
|
|
|
/** |
|
* 创建格式化面板 |
|
*/ |
|
private TextFormatPaneContainer createFormatPane() { |
|
TextFormatPaneContainer formatPane = new TextFormatPaneContainer(); |
|
|
|
AttributeChangeListener attributeChangeListener = new AttributeChangeListener() { |
|
@Override |
|
public void attributeChange() { |
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
@Override |
|
public void run() { |
|
// 耗时任务放线程中,让其他UI组件更新界面, |
|
// 防止多次调用此处每次获取的界面值不同,导致不断更新单元格格式 |
|
isEditing = true; |
|
boolean updateStyle = false; |
|
|
|
CellSelection cs = (CellSelection) tc.getSelection(); |
|
TemplateElementCase editingElementCase = tc.getEditingElementCase(); |
|
Set<TemplateCellElement> allCellElements = cs.getCellElements(); |
|
Style oldStyle = cellElement == null ? Style.DEFAULT_STYLE : cellElement.getStyle(); |
|
Style style = formatPane.update(oldStyle); |
|
for (TemplateCellElement cellElement : allCellElements) { |
|
Format elementFormat = cellElement.getStyle().getFormat(); |
|
Format paneFormat = style.getFormat(); |
|
if (!Objects.equals(paneFormat, elementFormat)) { |
|
// 点击单元格,但未设置格式时,不将单元格设置为编辑状态,防止将所选的每个单元格都设置为编辑状态 |
|
editingElementCase.addCellElement(cellElement); |
|
cellElement.setStyle(style); |
|
updateStyle = true; |
|
} |
|
} |
|
|
|
if (updateStyle) { |
|
// 防止频繁触发保存 |
|
fireTargetModified(); |
|
} |
|
|
|
isEditing = false; |
|
} |
|
}); |
|
|
|
} |
|
}; |
|
|
|
formatPane.addAttributeChangeListener(attributeChangeListener); |
|
|
|
return formatPane; |
|
} |
|
}
|
|
|