From 8622576dcad12a65cd0672429488c438c9c27a0c Mon Sep 17 00:00:00 2001 From: Starryi Date: Sun, 29 Aug 2021 01:55:01 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-58064=20=E3=80=90=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E3=80=91=E6=82=AC=E6=B5=AE=E5=85=83=E7=B4=A0?= =?UTF-8?q?-=E6=A0=B7=E5=BC=8F=E7=9A=84=E6=98=BE=E7=A4=BA=E5=90=8C?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E7=A8=BF=E4=B8=8D=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【问题原因】 实现表格悬浮元素样式设置面板的主题化 【改动思路】 同上 --- .../com/fr/design/report/ReportStylePane.java | 605 +++++++++++++++++- 1 file changed, 572 insertions(+), 33 deletions(-) diff --git a/designer-realize/src/main/java/com/fr/design/report/ReportStylePane.java b/designer-realize/src/main/java/com/fr/design/report/ReportStylePane.java index 558cf4291..e65e25949 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ReportStylePane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ReportStylePane.java @@ -1,52 +1,591 @@ package com.fr.design.report; -import com.fr.config.ServerPreferenceConfig; +import com.fr.base.NameStyle; +import com.fr.base.ScreenResolution; +import com.fr.base.Style; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.FineJOptionPane; -import com.fr.design.gui.imenu.UIMenuItem; -import com.fr.design.style.StylePane; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.ComparatorUtils; +import com.fr.design.fun.StyleUIConfigProvider; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.cell.settingpane.style.ThemedCellStyleListPane; +import com.fr.design.mainframe.theme.ui.NoEdgeTitleBorder; +import com.fr.design.style.AlignmentPane; +import com.fr.design.style.BorderPane; +import com.fr.design.style.BorderUtils; +import com.fr.design.style.FRFontPane; +import com.fr.design.style.FormatPane; +import com.fr.design.style.background.BackgroundPane; +import com.fr.general.FRFont; +import com.fr.grid.selection.CellSelection; +import com.fr.grid.selection.FloatSelection; +import com.fr.grid.selection.Selection; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.solution.sandbox.collection.PluginSandboxCollections; +import com.fr.report.cell.CellElement; +import com.fr.report.cell.DefaultTemplateCellElement; +import com.fr.report.cell.FloatElement; +import com.fr.report.cell.TemplateCellElement; +import com.fr.report.elementcase.ElementCase; +import com.fr.report.elementcase.TemplateElementCase; - -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; -public class ReportStylePane extends StylePane { +public class ReportStylePane extends BasicPane { + public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ + Toolkit.i18nText("Fine-Design_Style_Follow_Theme"), + Toolkit.i18nText("Fine-Design_Style_Not_Follow_Theme"), + }; + public static final int DEFAULT_SELECTED_INDEX = 0; - private static final int Y_OFFSET = 8; + private final PreviewArea previewArea; + private final UIButtonGroup followingThemeButtonGroup; + private final CustomFloatStyleSettingPane customStylePane; + private final ThemedCellStyleListPane themedCellStyleListPane; + private final CardLayout cardLayout; + private final JComponent[] panes = new JComponent[2]; + private final JPanel contentPane; public ReportStylePane() { - super(); - getPreviewArea().addMouseListener(new MouseAdapter() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + + previewArea = new PreviewArea(); + followingThemeButtonGroup = new UIButtonGroup<>(FOLLOWING_THEME_STRING_ARRAYS); + customStylePane = new CustomFloatStyleSettingPane(); + themedCellStyleListPane = new ThemedCellStyleListPane(); + panes[0] = createThemedStylePane(); + panes[1] = createCustomStylePane(); + cardLayout = new CardLayout(); + contentPane = createTabbedContentPane(); + + initializePane(); + + themedCellStyleListPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updatePreviewArea(); + } + }); + customStylePane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updatePreviewArea(); + } + }); + } + + private void initializePane() { + add(createPreviewPane(), BorderLayout.NORTH); + + JPanel settingContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel followingThemePane = createFollowingThemePane(); + followingThemePane.setBorder(BorderFactory.createEmptyBorder(20, 0, 10, 0)); + settingContainer.add(followingThemePane, BorderLayout.NORTH); + settingContainer.add(contentPane, BorderLayout.CENTER); + + add(settingContainer, BorderLayout.CENTER); + } + + private JPanel createPreviewPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Preview"))); + container.setPreferredSize(new Dimension(container.getPreferredSize().width, 60)); + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setBorder(BorderFactory.createEmptyBorder(4, 4, 2, 2)); + previewArea.setPreferredSize(new Dimension(container.getPreferredSize().width, 42)); + content.add(previewArea, BorderLayout.NORTH); + container.add(content, BorderLayout.NORTH); + return container; + } + + private JPanel createFollowingThemePane() { + followingThemeButtonGroup.setSelectedIndex(DEFAULT_SELECTED_INDEX); + followingThemeButtonGroup.addActionListener(new ActionListener() { @Override - public void mousePressed(MouseEvent evt) { - if (!SwingUtilities.isRightMouseButton(evt)) { - return; - } - - JPopupMenu popupMenu = new JPopupMenu(); - UIMenuItem menuItem = new UIMenuItem(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Save_As_Global_Style")); - popupMenu.add(menuItem); - menuItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - String name = FineJOptionPane.showInputDialog(getParent(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Input_The_Name_Of_Gloabel_Style")); - if (ComparatorUtils.equals(name, "")) { - return; + public void actionPerformed(ActionEvent e) { + int selectedIndex = followingThemeButtonGroup.getSelectedIndex(); + cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[selectedIndex]); + if (selectedIndex == 1) { + // 对于同一个单元格,跟随主题切换到自定义,若跟随主题面板有选中项,则自定义中的配置与其保持一致,否则自定义中配置保持不变 + NameStyle lastSelectedNameStyle = themedCellStyleListPane.updateBean(); + if (lastSelectedNameStyle != null) { + Style lastSelectedRealStyle = lastSelectedNameStyle.getRealStyle(); + try { + lastSelectedRealStyle = (Style) lastSelectedRealStyle.clone(); + if (lastSelectedRealStyle != null) { + customStylePane.populateBean(lastSelectedRealStyle); + } + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); } - if (ServerPreferenceConfig.getInstance().getStyle(name) == null) { - ServerPreferenceConfig.getInstance().putStyle(name, ReportStylePane.this.updateBean()); - } else { - FineJOptionPane.showMessageDialog(getParent(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_This_Name_Has_Exsit") + "!", com.fr.design.i18n.Toolkit.i18nText("FR-Designer_Warning"), JOptionPane.WARNING_MESSAGE); + } + } else { + // 对于同一个单元格,自定义切换到跟随主题,跟随主题应当清除选中项,即没有选中任何主题中的单元格样式, + // 因为还未选中,所以自定义中的配置保持不变,此时若用户切换会自定义,配置应当与之前一样 + themedCellStyleListPane.populateBean(null); + } + } + }); + + UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Style_Setting")); + + double p = TableLayout.PREFERRED; + + return TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ new Component[] { uiLabel, followingThemeButtonGroup} }, + new double[] { p }, new double[] { p, 160}, + IntervalConstants.INTERVAL_L1, 0); + } + + protected JPanel createTabbedContentPane() { + JPanel contentPane = new JPanel(cardLayout) { + @Override + public Dimension getPreferredSize() { + int selectedIndex = followingThemeButtonGroup.getSelectedIndex(); + if (selectedIndex < 0) { + return super.getPreferredSize(); + } else { + return panes[selectedIndex].getPreferredSize(); + } + } + }; + for (int i = 0; i < FOLLOWING_THEME_STRING_ARRAYS.length; i++) { + contentPane.add(panes[i], FOLLOWING_THEME_STRING_ARRAYS[i]); + } + cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[DEFAULT_SELECTED_INDEX]); + + return contentPane; + } + + private JPanel createThemedStylePane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(createTitleBorder(Toolkit.i18nText("Fine-Design_Style_Selecting"))); + themedCellStyleListPane.setBorder(BorderFactory.createEmptyBorder()); + UIScrollPane scrollPane = new UIScrollPane(themedCellStyleListPane); + scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 0)); + scrollPane.setPreferredSize(new Dimension(620, scrollPane.getPreferredSize().height)); + container.add(scrollPane, BorderLayout.CENTER); + return container; + } + + private JPanel createCustomStylePane() { + return customStylePane; + } + + public void setSelectedIndex(int index) { + if (0 <= index && index < FOLLOWING_THEME_STRING_ARRAYS.length) { + followingThemeButtonGroup.setSelectedIndex(index); + cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[index]); + } + } + + @Override + protected String title4PopupWindow() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style"); + } + + public int getSelectedIndex() { + return followingThemeButtonGroup.getSelectedIndex(); + } + + public void populate(ElementCasePane reportPane) { + populateBean(this.analyzeCurrentStyle(reportPane)); + updatePreviewArea(); + } + + private Style analyzeCurrentStyle(ElementCasePane reportPane) { + Style style = null; + + // p:从选中的CellElement那里先获得原始的Style. + Selection sel = reportPane.getSelection(); + if (sel instanceof FloatSelection) { + // got simple cell element from column and row. + ElementCase report = reportPane.getEditingElementCase(); + + FloatElement selectedFloatElement = report.getFloatElement(((FloatSelection) sel).getSelectedFloatName()); + style = selectedFloatElement.getStyle(); + } else { + CellSelection cs = (CellSelection) sel; + + // got simple cell element from column and row. + ElementCase report = reportPane.getEditingElementCase(); + CellElement editCellElement = report.getCellElement(cs.getColumn(), cs.getRow()); + + if (editCellElement != null && editCellElement.getStyle() != null) {// editCellElement + // cellstyle. + try { + style = (Style) editCellElement.getStyle().clone(); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + if (style == null) { + // peter:获取默认的Style. + style = Style.DEFAULT_STYLE; + } + + return style; + } + + public boolean update(ElementCasePane reportPane) { + return applyStyle(reportPane, updateBean()); + } + + private boolean applyStyle(ElementCasePane reportPane, Style style) { + TemplateElementCase report = reportPane.getEditingElementCase(); + Selection sel = reportPane.getSelection(); + if (sel instanceof FloatSelection) { + FloatElement floatElement = report.getFloatElement(((FloatSelection) sel).getSelectedFloatName()); + + // Apply style. + floatElement.setStyle(style); + } else { + CellSelection cs = (CellSelection) sel; + // Got editCellElement. + TemplateCellElement editCellElement; + + // 需要先行后列地增加新元素。 + for (int j = 0; j < cs.getRowSpan(); j++) { + for (int i = 0; i < cs.getColumnSpan(); i++) { + int column = i + cs.getColumn(); + int row = j + cs.getRow(); + + editCellElement = report.getTemplateCellElement(column, row); + if (editCellElement == null) { + editCellElement = new DefaultTemplateCellElement(column, row); + report.addCellElement(editCellElement); + } + + // Apply cellstyle. + editCellElement.setStyle(style); + } + } + } + + if (getSelectedIndex() == 1) { + // p:因为borderpane特殊,update borderpane + customStylePane.dealBorder(reportPane); + } + reportPane.repaint(); + return true; + } + + public Style updateBean() { + if (getSelectedIndex() == 0) { + NameStyle nameStyle = themedCellStyleListPane.updateBean(); + if (nameStyle != null) { + // 只有当前样式面板是跟随主题面板,且跟随主题面板中存在选中项,才使用该样式设置单元格 + return nameStyle; + } + } + return customStylePane.updateBean(); + } + + public void populateBean(Style style) { + if (style instanceof NameStyle) { + NameStyle nameStyle = (NameStyle) style; + setSelectedIndex(0); + themedCellStyleListPane.populateBean(nameStyle); + Style realStyle = nameStyle.getRealStyle(); + try { + realStyle = (Style) realStyle.clone(); + customStylePane.populateBean(realStyle); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } else { + setSelectedIndex(1); + customStylePane.populateBean(style); + } + } + + public void updatePreviewArea() { + previewArea.setStyle(updateBean()); + } + + private static class PreviewArea extends JComponent { + + private static final String paintText = "Report"; + private Style style = Style.DEFAULT_STYLE; + + public void setStyle(Style style) { + this.style = style; + repaint(); + } + + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + int resolution = ScreenResolution.getScreenResolution(); + + if (style == Style.DEFAULT_STYLE) { + // 如果是默认的style,就只写"Report"上去 + Style.paintContent(g2d, paintText, style, getWidth() - 3, getHeight() - 3, resolution); + return; + } + + Style.paintBackground(g2d, style, getWidth() - 3, getHeight() - 3); + + Style.paintContent(g2d, paintText, style, getWidth() - 3, getHeight() - 3, resolution); + + Style.paintBorder(g2d, style, getWidth() - 3, getHeight() - 3); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + } + + private static class CustomFloatStyleSettingPane extends BasicPane implements ChangeListener { + private static final int ALIGNMENT_INDEX = 1; + private static final int FONT_INDEX = 2; + private static final int BORDER_INDEX = 3; + private static final int BACKGROUND_INDEX = 4; + private static final int NEXT_TAB_INDEX = 5; + protected Style editing; + private FormatPane formatPane = null; + private AlignmentPane alignmentPane = null; + private FRFontPane frFontPane = null; + private BorderPane borderPane = null; + private BackgroundPane backgroundPane = null; + private static final List configList = PluginSandboxCollections.newSandboxList(); + private final List changeListeners = new ArrayList<>(); + + public CustomFloatStyleSettingPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + + UITabbedPane mainTabbedPane = new UITabbedPane(); + mainTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Format"), this.getFormatPane()); + mainTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Alignment"), FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane()); + mainTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sytle_FRFont"), FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane()); + mainTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane()); + mainTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane()); + + for (StyleUIConfigProvider config : configList) { + mainTabbedPane.addTab(config.configName(), FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane()); + } + mainTabbedPane.addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent evt) { + Object tabObj = evt.getSource(); + if (!(tabObj instanceof JTabbedPane)) { + return; + } + JTabbedPane tabbedPane = (JTabbedPane) tabObj; + + int selectedIndex = tabbedPane.getSelectedIndex(); + if (tabbedPane.getComponentAt(selectedIndex).getClass() == JPanel.class) {// 是JPanel,需要替换 + if (selectedIndex == ALIGNMENT_INDEX) { + tabbedPane.setComponentAt(selectedIndex, getAlignmentPane()); + } else if (selectedIndex == FONT_INDEX) { + tabbedPane.setComponentAt(selectedIndex, getFRFontPane()); + } else if (selectedIndex == BORDER_INDEX) { + tabbedPane.setComponentAt(selectedIndex, getBorderPane()); + } else if (selectedIndex == BACKGROUND_INDEX) { + tabbedPane.setComponentAt(selectedIndex, getBackgroundPane()); + } else if (configList.size() + NEXT_TAB_INDEX > selectedIndex && configList.get(selectedIndex - NEXT_TAB_INDEX) != null) { + tabbedPane.setComponentAt(selectedIndex, configList.get(selectedIndex - NEXT_TAB_INDEX).uiComponent(this)); + configList.get(selectedIndex - NEXT_TAB_INDEX).populateConfig(editing); } } - }); - GUICoreUtils.showPopupMenu(popupMenu, ReportStylePane.this, evt.getX() - 1, evt.getY() + Y_OFFSET); + stateChanged(evt); + } + }); + + add(mainTabbedPane, BorderLayout.CENTER); + } + + public void addChangeListener(ChangeListener changeListener) { + this.changeListeners.add(changeListener); + } + + protected FormatPane getFormatPane() { + if (this.formatPane == null) { + this.formatPane = new FormatPane(); + if (this.editing != null) { + this.formatPane.populate(this.editing.getFormat()); + } + } + + return this.formatPane; + } + + private AlignmentPane getAlignmentPane() { + if (this.alignmentPane == null) { + this.alignmentPane = new AlignmentPane(); + this.alignmentPane.addChangeListener(this); + if (this.editing != null) { + this.alignmentPane.populate(this.editing); + } } - }); + return this.alignmentPane; + } + + private FRFontPane getFRFontPane() { + if (this.frFontPane == null) { + this.frFontPane = new FRFontPane(); + this.frFontPane.addChangeListener(this); + if (this.editing != null) { + this.frFontPane.populate(this.editing.getFRFont()); + } + } + + return this.frFontPane; + } + + private BorderPane getBorderPane() { + if (this.borderPane == null) { + this.borderPane = new BorderPane(); + this.borderPane.addChangeListener(this); + + if (this.editing != null) { + this.borderPane.populate(this.editing); + } + } + + return this.borderPane; + } + + private BackgroundPane getBackgroundPane() { + if (this.backgroundPane == null) { + this.backgroundPane = new BackgroundPane(); + this.backgroundPane.addChangeListener(this); + if (this.editing != null) { + this.backgroundPane.populate(this.editing.getBackground()); + } + } + + return this.backgroundPane; + } + + public void populateBean(Style ob) { + this.editing = ob == null ? Style.getInstance() : ob; + + if (this.formatPane != null) { + this.formatPane.populate(editing.getFormat()); + } + if (this.alignmentPane != null) { + this.alignmentPane.populate(editing); + } + if (this.frFontPane != null) { + this.frFontPane.populate(editing.getFRFont()); + } + if (this.borderPane != null) { + this.borderPane.populate(editing); + } + if (this.backgroundPane != null) { + this.backgroundPane.populate(editing.getBackground()); + } + for(StyleUIConfigProvider tabConfig : configList){ + tabConfig.populateConfig(this.editing); + } + } + + public Style updateBean() { + // need the check the valid of CellAlignment pane. + try { + if (this.alignmentPane != null) { + this.alignmentPane.checkValid(); + } + } catch (Exception exp) { + FineJOptionPane.showMessageDialog(this, exp.getMessage()); + return editing; + } + + Style style = editing; + if (this.formatPane != null) { + style = style.deriveFormat(this.formatPane.update()); + } + if (this.alignmentPane != null) { + style = this.alignmentPane.update(style); + } + if (this.frFontPane != null) { + style = style.deriveFRFont(this.frFontPane.update()); + } + if (this.borderPane != null) { + style = this.borderPane.update(style); + } + if (this.backgroundPane != null) { + style = style.deriveBackground(this.backgroundPane.update()); + } + for(StyleUIConfigProvider tabConfig : configList){ + style = tabConfig.updateConfig(); + } + + return style; + } + + public void dealBorder(ElementCasePane reportPane) { + if (this.borderPane != null) { + BorderUtils.update(reportPane, this.borderPane.update()); + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + + @Override + public void stateChanged(ChangeEvent e) { + for (ChangeListener changeListener: changeListeners) { + changeListener.stateChanged(e); + } + } + } + + private Border createTitleBorder(String title) { + return new NoEdgeTitleBorder( + BorderFactory.createCompoundBorder( + BorderFactory.createEmptyBorder( + 0, + 0, + 0, + 0), + new UIRoundedBorder( + UIConstants.TITLED_BORDER_COLOR, + 1, + 10) + ), + title, + TitledBorder.LEADING, + TitledBorder.TOP, + FRFont.getInstance().deriveFont(12F), + new Color(0x2F8EF1) + ); } }