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.
360 lines
14 KiB
360 lines
14 KiB
package com.fr.design.mainframe.theme; |
|
|
|
import com.fr.base.theme.FineColorSynchronizer; |
|
import com.fr.base.theme.TemplateTheme; |
|
import com.fr.base.theme.TemplateThemeConfig; |
|
import com.fr.base.theme.settings.ThemedCellStyleList; |
|
import com.fr.base.theme.settings.ThemedColorScheme; |
|
import com.fr.widgettheme.ThemePreviewTerminal; |
|
import com.fr.widgettheme.util.WidgetThemeDesignerUtils; |
|
import com.fr.design.ExtraDesignClassManager; |
|
import com.fr.design.beans.BasicBeanPane; |
|
import com.fr.design.designer.IntervalConstants; |
|
import com.fr.design.fun.TemplateThemePaneProvider; |
|
import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; |
|
import com.fr.design.gui.frpane.AttributeChangeListener; |
|
import com.fr.design.gui.frpane.UITabbedPane; |
|
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.theme.edit.CellStyleListEditPane; |
|
import com.fr.design.mainframe.theme.edit.ChartStyleEditPane; |
|
import com.fr.design.mainframe.theme.edit.ui.ColorListPane; |
|
import com.fr.design.mainframe.theme.edit.ui.LabelUtils; |
|
import com.fr.design.mainframe.theme.ui.AutoCheckTextField; |
|
import com.fr.design.mainframe.theme.ui.AutoCheckThemeNameTextField; |
|
import com.fr.design.mainframe.theme.ui.BorderUtils; |
|
import com.fr.general.GeneralContext; |
|
import com.fr.plugin.observer.PluginEvent; |
|
import com.fr.plugin.observer.PluginEventListener; |
|
import com.fr.stable.StringUtils; |
|
import com.fr.widgettheme.theme.edit.ParamContainerStyleEditPane; |
|
import com.fr.widgettheme.theme.edit.widget.WidgetStyleEditContainerPane; |
|
|
|
import javax.swing.BorderFactory; |
|
import javax.swing.JComponent; |
|
import javax.swing.JPanel; |
|
import javax.swing.event.ChangeEvent; |
|
import javax.swing.event.ChangeListener; |
|
import java.awt.BorderLayout; |
|
import java.awt.Color; |
|
import java.awt.Component; |
|
import java.awt.Dimension; |
|
import java.util.ArrayList; |
|
import java.util.List; |
|
import java.util.Set; |
|
|
|
/** |
|
* @author Starryi |
|
* @version 1.0 |
|
* Created by Starryi on 2021/8/13 |
|
*/ |
|
public abstract class TemplateThemeEditorPane<T extends TemplateTheme> extends JPanel { |
|
public static final int LEFT_TITLE_PANE_HEIGHT = 539; |
|
|
|
public static final int RIGHT_PANE_WIDTH = 362; |
|
public static final int RIGHT_PANE_HEIGHT = LEFT_TITLE_PANE_HEIGHT; |
|
|
|
protected AutoCheckThemeNameTextField<T> nameTextField; |
|
private UILabel nameErrorLabel; |
|
protected ColorListPane colorListPane; |
|
protected CellStyleListEditPane cellStyleSettingPane; |
|
protected ChartStyleEditPane chartStyleSettingPane; |
|
protected final List<BasicBeanPane<T>> extraPaneList = new ArrayList<>(); |
|
|
|
protected boolean isPopulating = false; |
|
protected UITabbedPane uiTabbedPane; |
|
|
|
private final TemplateThemeConfig<T> config; |
|
|
|
private boolean refreshingThemedColor = false; |
|
private T theme; |
|
|
|
private AttributeChangeListener changeListener; |
|
private AutoCheckTextField.CheckListener themeNameCheckListener; |
|
|
|
public TemplateThemeEditorPane(TemplateThemeConfig<T> config) { |
|
super(); |
|
this.config = config; |
|
theme = config.createNewTheme(); |
|
initializePane(); |
|
} |
|
|
|
private void initializePane() { |
|
setLayout(new BorderLayout(0, 0)); |
|
setPreferredSize(new Dimension(RIGHT_PANE_WIDTH, RIGHT_PANE_HEIGHT)); |
|
JPanel nameEditPane = createNameEditPane(); |
|
add(nameEditPane, BorderLayout.NORTH); |
|
|
|
JPanel settingPane = new JPanel(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); |
|
settingPane.add(createColorSchemeEditPane(), BorderLayout.NORTH); |
|
settingPane.add(createCustomEditorsPane(), BorderLayout.CENTER); |
|
|
|
add(settingPane, BorderLayout.CENTER); |
|
} |
|
|
|
private JPanel createNameEditPane() { |
|
nameErrorLabel = LabelUtils.createLabel(StringUtils.EMPTY, Color.RED); |
|
nameErrorLabel.setVisible(false); |
|
|
|
nameTextField = new AutoCheckThemeNameTextField<>(); |
|
nameTextField.setThemeConfig(config); |
|
nameTextField.setEditable(false); |
|
nameTextField.setEnabled(false); |
|
nameTextField.setPreferredSize(new Dimension(165, 20)); |
|
nameTextField.setNameCheckListener(new AutoCheckTextField.CheckListener() { |
|
@Override |
|
public void onChecked(String error, boolean valid) { |
|
nameErrorLabel.setVisible(StringUtils.isNotEmpty(error)); |
|
nameErrorLabel.setText(error); |
|
|
|
themeNameCheckListener.onChecked(error, valid); |
|
} |
|
}); |
|
|
|
double p = TableLayout.PREFERRED; |
|
|
|
JPanel container = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ |
|
new Component[] { LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Name")), nameTextField }, |
|
new Component[] { null, nameErrorLabel }, |
|
}, new double[] { 20, 20}, new double[] { p, 165}, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_W0); |
|
|
|
container.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); |
|
return container; |
|
} |
|
|
|
private JPanel createColorSchemeEditPane() { |
|
colorListPane = new ColorListPane(); |
|
|
|
double p = TableLayout.PREFERRED; |
|
double[] rowSize = new double[]{p, p, p}; |
|
double[] columnSize = {p, p}; |
|
|
|
JPanel colorListContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
colorListContainerPane.add(colorListPane, BorderLayout.WEST); |
|
|
|
UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Tip"), new Color(153, 153, 153)); |
|
|
|
JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
|
{LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Label")), colorListContainerPane}, |
|
{null, tipLabel}, |
|
}, |
|
rowSize, columnSize, 18, 7); |
|
content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
|
|
|
JPanel borderContainer = new JPanel(new BorderLayout()); |
|
borderContainer.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Title"))); |
|
borderContainer.add(content); |
|
|
|
JPanel container = new JPanel(new BorderLayout()); |
|
container.add(borderContainer, BorderLayout.CENTER); |
|
|
|
colorListPane.addColorChangeListener(new ChangeListener() { |
|
@Override |
|
public void stateChanged(ChangeEvent e) { |
|
if (refreshingThemedColor) { |
|
return; |
|
} |
|
List<Color> colors = colorListPane.update(); |
|
refreshingThemedColor = true; |
|
onColorSchemeChanged(colors); |
|
refreshingThemedColor = false; |
|
|
|
fireAttributeChange(); |
|
} |
|
}); |
|
|
|
return container; |
|
} |
|
private void onColorSchemeChanged(List<Color> colors) { |
|
T theme = updateBean(); |
|
theme = (T) FineColorSynchronizer.flush(theme, colors); |
|
populateBean4CustomEditors(theme); |
|
this.repaint(); |
|
} |
|
|
|
protected JPanel createCustomEditorsPane() { |
|
JPanel container = new JPanel(new BorderLayout()); |
|
container.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Custom_Settings_Title"))); |
|
|
|
uiTabbedPane = new UITabbedPane(); |
|
uiTabbedPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 1)); |
|
container.add(uiTabbedPane, BorderLayout.CENTER); |
|
initPluginListener(); |
|
return container; |
|
} |
|
|
|
public void addCustomEditorPane(String title, final Component component) { |
|
AbstractAttrNoScrollPane settingPane = new NoBorderAbstractAttrNoScrollPane() { |
|
@Override |
|
protected JPanel createContentPane() { |
|
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
contentPane.add(component, BorderLayout.CENTER); |
|
return contentPane; |
|
} |
|
}; |
|
settingPane.addAttributeChangeListener(new AttributeChangeListener() { |
|
@Override |
|
public void attributeChange() { |
|
fireAttributeChange(); |
|
} |
|
}); |
|
uiTabbedPane.addTab(title, settingPane); |
|
} |
|
|
|
protected void refreshExtraAdvancedPane() { |
|
extraPaneList.clear(); |
|
if(WidgetThemeDesignerUtils.enableWidgetEnhance()) { |
|
extraPaneList.add(new ParamContainerStyleEditPane<>()); |
|
extraPaneList.add(new WidgetStyleEditContainerPane<>()); |
|
} |
|
Set<TemplateThemePaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(TemplateThemePaneProvider.XML_TAG); |
|
for (TemplateThemePaneProvider<T> provider : providers) { |
|
insertShortCut(provider.getInsertPosition(extraPaneList.size()), provider.getTab()); |
|
} |
|
for (BasicBeanPane<T> pane : extraPaneList) { |
|
addCustomEditorPane(pane.getTitle(), pane); |
|
} |
|
} |
|
|
|
private void insertShortCut(int index, BasicBeanPane<T> pane) { |
|
int size = extraPaneList.size(); |
|
index = Math.min(index, size); |
|
extraPaneList.add(index, pane); |
|
} |
|
|
|
private void initPluginListener() { |
|
GeneralContext.listenPluginRunningChanged(new PluginEventListener() { |
|
@Override |
|
public void on(PluginEvent event) { |
|
refreshExtraAdvancedPane(); |
|
} |
|
}, pluginContext -> pluginContext.getRuntime().contain(TemplateThemePaneProvider.XML_TAG)); |
|
} |
|
|
|
protected JPanel createCellStyleSettingPane() { |
|
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
cellStyleSettingPane = new CellStyleListEditPane(); |
|
cellStyleSettingPane.registerAttrChangeListener(new AttributeChangeListener() { |
|
@Override |
|
public void attributeChange() { |
|
fireAttributeChange(); |
|
} |
|
}); |
|
container.add(cellStyleSettingPane); |
|
return container; |
|
} |
|
protected JPanel createChartStyleSettingPane() { |
|
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
chartStyleSettingPane = new ChartStyleEditPane(); |
|
container.add(chartStyleSettingPane); |
|
return container; |
|
} |
|
|
|
public void populateBean(T theme) { |
|
this.theme = theme; |
|
isPopulating = true; |
|
|
|
String name = theme.getName(); |
|
setThemeNameEditable(StringUtils.isEmpty(name)); |
|
|
|
nameTextField.setText(name); |
|
|
|
colorListPane.populate(theme.getColorScheme().getColors()); |
|
|
|
populateBean4CustomEditors(theme); |
|
for (BasicBeanPane<T> pane : extraPaneList) { |
|
pane.populateBean(theme); |
|
} |
|
isPopulating = false; |
|
} |
|
|
|
protected void populateBean4CustomEditors(T theme) { |
|
cellStyleSettingPane.populateBean(theme.getCellStyleList()); |
|
chartStyleSettingPane.populateBean(theme.getChartStyle()); |
|
} |
|
|
|
public T updateBean() { |
|
if (theme == null) { |
|
theme = config.createNewTheme(); |
|
} |
|
|
|
theme.setName(this.nameTextField.getText()); |
|
|
|
ThemedColorScheme colorScheme = theme.getColorScheme(); |
|
colorScheme.setColors(this.colorListPane.update()); |
|
theme.setColorScheme(colorScheme); |
|
|
|
updateBean4CustomEditors(theme); |
|
for (BasicBeanPane<T> pane : extraPaneList) { |
|
pane.updateBean(theme); |
|
} |
|
return theme; |
|
} |
|
|
|
protected void updateBean4CustomEditors(T theme) { |
|
ThemedCellStyleList cellStyleConfig = this.cellStyleSettingPane.updateBean(); |
|
theme.setCellStyleList(cellStyleConfig); |
|
|
|
theme.setChartStyle(this.chartStyleSettingPane.updateBean()); |
|
} |
|
|
|
public void setThemeNameEditable(boolean editable) { |
|
nameTextField.setEditable(editable); |
|
nameTextField.setEnabled(editable); |
|
} |
|
|
|
public boolean checkNameValid() { |
|
return nameTextField.checkValid(); |
|
} |
|
|
|
public String getThemeName() { |
|
return nameTextField.getText(); |
|
} |
|
|
|
public List<Color> getCurrentColorScheme() { |
|
return colorListPane.update(); |
|
} |
|
|
|
private void fireAttributeChange() { |
|
if (!isPopulating && !refreshingThemedColor && changeListener != null) { |
|
changeListener.attributeChange(); |
|
} |
|
} |
|
|
|
public void addAttributeChangeListener(AttributeChangeListener changeListener) { |
|
this.changeListener = changeListener; |
|
} |
|
public void addThemeNameCheckListener(AutoCheckTextField.CheckListener checkListener) { |
|
this.themeNameCheckListener = checkListener; |
|
} |
|
|
|
private static abstract class NoBorderAbstractAttrNoScrollPane extends AbstractAttrNoScrollPane { |
|
@Override |
|
protected void initContentPane() { |
|
super.initContentPane(); |
|
if (leftContentPane != null) { |
|
// 修正 AbstractAttrNoScrollPane 的默认行为 |
|
leftContentPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* 开启控件显示增强时,从配置面板处获取主题样式预览的终端类型 |
|
* 默认为PC端,兼容原有场景 |
|
*/ |
|
public ThemePreviewTerminal getWidgetStyleEditorTerminal() { |
|
if (!WidgetThemeDesignerUtils.enableWidgetEnhance()) { |
|
return ThemePreviewTerminal.PC; |
|
} |
|
for (BasicBeanPane<T> pane : extraPaneList) { |
|
if (pane instanceof WidgetStyleEditContainerPane) { |
|
return ((WidgetStyleEditContainerPane<T>) pane).getTerminalStyle(); |
|
} |
|
} |
|
return ThemePreviewTerminal.PC; |
|
} |
|
} |