diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java index 265043283b..3df87ac658 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java @@ -5,6 +5,7 @@ import com.fr.base.theme.TemplateThemeConfig; import com.fr.concurrent.NamedThreadFactory; import com.fr.module.ModuleContext; +import javax.swing.SwingUtilities; import java.util.concurrent.ExecutorService; /** @@ -48,7 +49,13 @@ public class AsyncThemeFetcher { return; } if (callback != null) { - callback.afterCachedFetch(theme); + // 后续任务不要在工作线程中执行,从而确保只在EDT线程操作UI + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + callback.afterCachedFetch(theme); + } + }); } } }); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java index 933ce2ad31..d014199f35 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java @@ -16,7 +16,6 @@ import com.fr.stable.StringUtils; import javax.swing.BorderFactory; import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.SwingUtilities; import java.awt.BorderLayout; @@ -27,10 +26,10 @@ import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.RenderingHints; +import java.awt.Toolkit; import java.awt.Window; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.concurrent.ExecutorService; /** * @author Starryi @@ -51,7 +50,7 @@ public class TemplateThemeBlock extends JPanel { private final Icon profileIcon = IOUtils.readIcon("/com/fr/design/icon/icon_edit.png"); private final boolean displayTheme4NewTemplateMarker; - private UILabel thumbnailLabel; + private final ThumbnailPane thumbnailPane; // UIButton会影响Block的手势监听,这里使用UILabel代替,点击事件也有Block代为处理 private UILabel profileButton; private boolean selected = false; @@ -67,6 +66,7 @@ public class TemplateThemeBlock extends JPanel { this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker; this.config = config; this.profilePane = profilePane; + this.thumbnailPane = new ThumbnailPane(); initializePane(); addMouseListener(new MouseAdapter() { @@ -100,8 +100,8 @@ public class TemplateThemeBlock extends JPanel { setPreferredSize(new Dimension(getPreferredSize().width, HEIGHT)); setBackground(Color.WHITE); - thumbnailLabel = new UILabel(); - thumbnailLabel.setPreferredSize(new Dimension(getPreferredSize().width, THUMBNAIL_HEIGHT)); + thumbnailPane.setBackground(Color.WHITE); + thumbnailPane.setPreferredSize(new Dimension(getPreferredSize().width, THUMBNAIL_HEIGHT)); JPanel infoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); infoPane.setBackground(Color.WHITE); @@ -115,23 +115,20 @@ public class TemplateThemeBlock extends JPanel { addProfileButton(infoPane); } - add(thumbnailLabel, BorderLayout.CENTER); + add(thumbnailPane, BorderLayout.CENTER); add(infoPane, BorderLayout.SOUTH); } public void setTheme(T theme) { this.theme = theme; - thumbnailLabel.setIcon(null); + Image image = null; if (theme != null) { ThemeThumbnail thumbnail = theme.getThumbnail(); if (thumbnail != null) { - Image image = thumbnail.getImage(); - if (image != null) { - thumbnailLabel.setIcon(new ImageIcon(image)); - } + image = thumbnail.getImage(); } } - repaint(); + thumbnailPane.setThumbnail(image); } public T getTheme() { @@ -158,7 +155,7 @@ public class TemplateThemeBlock extends JPanel { int y = e.getY(); int profileButtonX = profileButton.getX(); - int profileButtonY = thumbnailLabel.getHeight() + profileButton.getY(); + int profileButtonY = thumbnailPane.getHeight() + profileButton.getY(); boolean inX = profileButtonX <= x && x <= profileButtonX + profileButton.getWidth(); boolean inY = profileButtonY <= y && y <= profileButtonY + profileButton.getHeight(); @@ -205,4 +202,53 @@ public class TemplateThemeBlock extends JPanel { GraphHelper.draw(g, rectangle, Constants.LINE_MEDIUM); } } + + private static class ThumbnailPane extends JPanel { + private static final Image LOADING_IMAGE = Toolkit.getDefaultToolkit().createImage(ThumbnailPane.class.getResource("/com/fr/design/images/mainframe/loading.gif")); + private Image thumbnail = null; + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + paintCenterImage(g2d, thumbnail != null ? thumbnail : LOADING_IMAGE); + } + + private void paintCenterImage(Graphics2D g2d, Image image) { + if (image == null) { + return; + } + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + int width = getWidth(); + int height = getHeight(); + int imgWidth = image.getWidth(null); + int imgHeight = image.getHeight(null); + + if (width <= 0 || height <= 0 || imgWidth <= 0 || imgHeight <= 0) { + return; + } + + float imgAspect = 1.0F * imgWidth / imgHeight; + + if (1.0F * width / height > 1.0F * imgWidth / imgHeight) { + imgHeight = height; + imgWidth = (int) (1.0F * imgHeight * imgAspect); + } else { + imgWidth = width; + imgHeight = (int) (1.0F * imgWidth / imgAspect); + } + int x = (width - imgWidth) / 2; + int y = (height - imgHeight) / 2; + + g2d.drawImage(image, x, y, imgWidth, imgHeight, null); + } + + public void setThumbnail(Image thumbnail) { + this.thumbnail = thumbnail; + invalidate(); + repaint(); + } + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java index 8da77c3780..bf93c6345a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java @@ -17,11 +17,13 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.icon.IconPathConstants; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.mainframe.theme.edit.CellStyleListEditPane; import com.fr.design.menu.MenuDef; import com.fr.design.menu.ToolBarDef; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; +import com.fr.transaction.CallBackAdaptor; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; @@ -45,6 +47,8 @@ import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import static com.fr.design.i18n.Toolkit.i18nText; + /** * @author Starryi * @version 1.0 @@ -172,7 +176,16 @@ public class TemplateThemeManagePane extends BasicPane public void actionPerformed(ActionEvent e) { T theme = themeListPane.getSelectedTheme(); if (theme != null) { - config.setThemeName4NewTemplate(theme.getName()); + config.setThemeName4NewTemplate(theme.getName(), new CallBackAdaptor() { + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); } } }); @@ -221,10 +234,14 @@ public class TemplateThemeManagePane extends BasicPane Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Delete_Tip", theme.getName()), Toolkit.i18nText("Fine-Design_Basic_Delete"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (result == JOptionPane.YES_OPTION) { - Configurations.modify(new WorkerFacade(config.getClass()) { + config.removeTheme(theme.getName(), new CallBackAdaptor() { @Override - public void run() { - config.removeTheme(theme.getName()); + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); } }); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java index cedc63f3f0..0abd6a7bc9 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java @@ -7,6 +7,7 @@ import com.fr.base.theme.settings.ThemeThumbnail; import com.fr.base.theme.settings.ThemedCellStyleList; import com.fr.base.theme.settings.ThemedChartStyle; import com.fr.base.theme.settings.ThemedColorScheme; +import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.design.gui.frpane.UITabbedPane; @@ -34,7 +35,9 @@ import com.fr.transaction.WorkerFacade; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JDialog; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; @@ -51,6 +54,8 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List; +import static com.fr.design.i18n.Toolkit.i18nText; + /** * @author Starryi * @version 1.0 @@ -238,9 +243,12 @@ public abstract class TemplateThemeProfilePane extends JPanel previewLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); previewLabelPane.add(LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Preview_Label")), BorderLayout.NORTH); + UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Tip"), new Color(153, 153, 153)); + tipLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ {LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Label")), colorListPane}, - {null, LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Tip"), new Color(0XC6C6C6), 10)}, + {null, tipLabel}, {previewLabelPane, extendedContainer}, }, rowSize, columnSize, 18, 7); @@ -384,12 +392,7 @@ public abstract class TemplateThemeProfilePane extends boolean canBeSaved = checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, nameTextField, nameErrorLabel, saveButton); if (canBeSaved && theme != null) { theme.setName(nameTextField.getText()); - Configurations.modify(new WorkerFacade(config.getClass()) { - @Override - public void run() { - config.addTheme(theme, true); - } - }.addCallBack(new CallBackAdaptor() { + config.addTheme(theme, true, new CallBackAdaptor() { @Override public void afterCommit() { super.afterCommit(); @@ -397,7 +400,16 @@ public abstract class TemplateThemeProfilePane extends nameTextField.setEnabled(false); saveAsButton.setEnabled(true); } - })); + + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeProfilePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); } } }); @@ -540,20 +552,23 @@ public abstract class TemplateThemeProfilePane extends newThemeObject.setName(name); newThemeObject.setRemovable(true); newThemeObject.setMutable(true); - T finalNewThemeObject = newThemeObject; - Configurations.modify(new WorkerFacade(config.getClass()) { - @Override - public void run() { - config.addTheme(finalNewThemeObject, true); - } - }.addCallBack(new CallBackAdaptor() { + config.addTheme(newThemeObject, true, new CallBackAdaptor() { @Override public void afterCommit() { super.afterCommit(); exit(); parent.exit(); } - })); + + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeProfilePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java index bb78d2fc0b..87a12a9ddf 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java @@ -45,7 +45,7 @@ public class ComponentStyleEditPane extends JPanel { new String[] { Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Title"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Body"), - Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Background") + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Integral") }, new JComponent[] { createTabContainer(componentTitleStylePane), createTabContainer(componentBodyStylePane), createTabContainer(componentIntegralStylePane) } ); @@ -119,7 +119,7 @@ public class ComponentStyleEditPane extends JPanel { JPanel tipLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); tipLabelPane.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); - UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Style_Tip"), new Color(0XC6C6C6), 10); + UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Style_Tip"), new Color(153, 153, 153)); tipLabelPane.add(tipLabel); container.add(tipLabelPane, BorderLayout.NORTH); diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java index ee4a88409e..09170b8c3b 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java +++ b/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java @@ -97,7 +97,7 @@ public class LayoutStylePane extends BasicBeanPane { return null; } this.integralStylePane = new ComponentIntegralStylePane(SETTING_LABEL_WIDTH, supportBorderImage, supportCornerRadius); - return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Background_Style"), this.integralStylePane); + return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Integral_Style"), this.integralStylePane); } protected JPanel createNamedSubStylePane(String name, JPanel stylePane) { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/ThemedCellStyleListPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/ThemedCellStyleListPane.java index 1ddf279c7a..59a61e2d10 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/ThemedCellStyleListPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/ThemedCellStyleListPane.java @@ -7,18 +7,20 @@ import com.fr.base.theme.TemplateTheme; import com.fr.base.theme.settings.ThemedCellStyle; import com.fr.design.beans.FurtherBasicBeanPane; import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerBean; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; -import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; import javax.swing.BorderFactory; -import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; +import javax.swing.JComponent; import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.BorderLayout; @@ -28,52 +30,21 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.io.Serializable; import java.util.List; public class ThemedCellStyleListPane extends FurtherBasicBeanPane implements DesignerBean { private static final int LEFT_BORDER = 10; private static final int RIGHT_BORDER = 10; - private DefaultListModel defaultListModel; - private JList styleList; + private final DefaultListModel defaultListModel; + private final JList styleList; private ChangeListener changeListener; public ThemedCellStyleListPane() { defaultListModel = new DefaultListModel<>(); styleList = new JList<>(defaultListModel); - DefaultListCellRenderer render = new DefaultListCellRenderer() { - private Style nameStyle; - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - - if (value instanceof Style) { - this.nameStyle = (Style) value; - this.setText(" "); - } - this.setPreferredSize(new Dimension(210, 22)); - return this; - } - - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - - if (nameStyle == null) { - return; - } - String text = "abcedfgh"; - if (nameStyle instanceof NameStyle) { - text = ((NameStyle) nameStyle).getName(); - } - Style.paintBackground((Graphics2D) g, nameStyle, getWidth() - 1, getHeight() - 1); - Style.paintContent((Graphics2D) g, text, nameStyle, getWidth() - 1, getHeight() - 1, ScreenResolution.getScreenResolution()); - Style.paintBorder((Graphics2D) g, nameStyle, getWidth() - 1, getHeight() - 1); - } - - }; - styleList.setCellRenderer(render); + styleList.setCellRenderer(new RadioButtonListCellRenderer()); setLayout(FRGUIPaneFactory.createBorderLayout()); add(styleList, BorderLayout.CENTER); setBorder(BorderFactory.createEmptyBorder(0 ,LEFT_BORDER, 0, RIGHT_BORDER)); @@ -167,4 +138,66 @@ public class ThemedCellStyleListPane extends FurtherBasicBeanPane imp styleList.setModel(defaultListModel); } + private static class RadioButtonListCellRenderer extends JPanel implements ListCellRenderer, Serializable { + + private final UIRadioButton button; + private final PreviewArea previewArea; + + public RadioButtonListCellRenderer() { + super(); + setLayout(new BorderLayout(20, 0)); + setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + setPreferredSize(new Dimension(getPreferredSize().width, 40)); + button = new UIRadioButton(); + previewArea = new PreviewArea(); + add(button, BorderLayout.WEST); + add(previewArea, BorderLayout.CENTER); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + button.setSelected(isSelected); + previewArea.setStyle((Style) value); + return this; + } + } + + private static class PreviewArea extends JComponent { + + private String paintText = "Report"; + private Style style = Style.DEFAULT_STYLE; + + public void setStyle(Style style) { + this.style = style; + if (style instanceof NameStyle) { + paintText = ((NameStyle) style).getName(); + } + repaint(); + } + + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + int resolution = ScreenResolution.getScreenResolution(); + + g.clipRect(0, 0, getWidth() - 3, getHeight() - 3); + + 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(); + } + } } \ No newline at end of file