帆软报表设计器源代码。
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.
 
 
 
 

428 lines
17 KiB

package com.fr.startup.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.dialog.UIExpandDialog;
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.VerticalFlowLayout;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.ColorUtils;
import com.fr.design.utils.ThemeUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.exit.DesignerExiter;
import com.fr.general.GeneralUtils;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fanruan.product.ProductConstants;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.os.OperatingSystem;
import com.fr.start.common.DesignerStartupContext;
import com.fr.startup.metric.DesignerMetrics;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Map;
/**
* 启动页
* 见<a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
* <p>
* created by Harrison on 2022/07/06
**/
public class StartupPageWindow extends JFrame {
private static final Color HOVER_COLOR = new Color(65, 155, 249);
private static final Color SEP_COLOR = new Color(224, 224, 225);
private static final int GROUP_WIDTH = 600;
private static final int RECENT_FILE_LIMIT = 6;
private static final int RECENT_FILE_SCROLL = RECENT_FILE_LIMIT + 1;
private static final int WORKSPACE_PANEL_WIDTH = 180;
private static final int TITLE_FONT_SIZE = 24;
private static final int ITEM_VERTICAL_GAP = 5;
private static final Dimension SCREEN_SIZE = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
private static final BufferedImage BACKGROUND_IMAGE = IOUtils.readImage("com/fr/design/startup/startup_page_background.jpg");
private StartupPageWorkspacePanel workspacePanel;
private JPanel recentOpenPanel;
private JPanel contentPane;
private JPanel body;
public StartupPageWindow(StartupPageModel pageModel) {
patchUIAction(pageModel);
setLayout(new BorderLayout());
initCenter(pageModel);
// Workspace-detail
setSize(SCREEN_SIZE);
setDefaultTitle();
addDefaultListeners();
repaint();
validate();
revalidate();
setFullScreen();
}
private void initCenter(StartupPageModel pageModel) {
initHeaderPanel();
initWorkspacePanel(pageModel);
initRecentOpenPanel(pageModel);
initContentPanel();
}
private void initHeaderPanel() {
this.body = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.body.setBackground(new Color(0, 0, 0, 0));
JPanel headerPanel = createHeader();
this.body.add(headerPanel, BorderLayout.NORTH);
}
private void initRecentOpenPanel(StartupPageModel pageModel) {
this.recentOpenPanel = generateRecentOpenPanel(pageModel);
this.body.add(recentOpenPanel, BorderLayout.SOUTH);
}
private void initContentPanel() {
this.contentPane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(BACKGROUND_IMAGE, 0, 0, SCREEN_SIZE.width, SCREEN_SIZE.height, this);
}
};
this.contentPane.setLayout(getCenterLayout(body));
this.contentPane.add(this.body, BorderLayout.CENTER);
this.contentPane.setPreferredSize(this.body.getPreferredSize());
add(this.contentPane, BorderLayout.CENTER);
}
private void initWorkspacePanel(StartupPageModel pageModel) {
// Workspace-description
this.workspacePanel = generateWorkspacePanel(pageModel);
this.body.add(workspacePanel, BorderLayout.CENTER);
workspacePanel.setSelectWorkspaceRunnable(new Runnable() {
@Override
public void run() {
JPanel newPanel = generateRecentOpenPanel(pageModel);
body.remove(recentOpenPanel);
recentOpenPanel = newPanel;
body.add(recentOpenPanel, BorderLayout.SOUTH);
validate();
repaint();
}
});
}
@NotNull
private static JPanel createHeader() {
// Header
UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Startup_Page_Select_Workspace"));
Font font = label.getFont();
Font titleFont = font.deriveFont(font.getStyle(), TITLE_FONT_SIZE);
label.setFont(titleFont);
JPanel headerPanel = new JPanel();
LayoutManager centerFlowLayout = FRGUIPaneFactory.createCenterFlowLayout();
headerPanel.setLayout(centerFlowLayout);
headerPanel.add(label);
headerPanel.setBackground(new Color(0, 0, 0, 0));
return headerPanel;
}
/**
* 1-mac启动时全屏
* 2-windows 则居中处理
*/
private void setFullScreen() {
if (OperatingSystem.isMacos()) {
this.setLocation(0, 0);
this.setSize(SCREEN_SIZE.width, SCREEN_SIZE.height);
} else {
GUICoreUtils.setWindowFullScreen(this);
}
}
private void addDefaultListeners() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
DesignerExiter.getInstance().execute();
}
});
}
private void setDefaultTitle() {
StringBuilder sb = new StringBuilder();
sb.append(ProductConstants.APP_NAME);
sb.append(" ");
sb.append(GeneralUtils.getVersion());
sb.append(" ");
sb.append(ProductConstants.BRANCH);
sb.append(" ");
sb.append(Toolkit.i18nText("Fine-Design_Startup_Page_Title"));
setTitle(sb.toString());
}
private void patchUIAction(StartupPageModel pageModel) {
Runnable selectAndOpenLastTemplateRunnable = pageModel.getOpenLastTemplateRunnable();
pageModel.setOpenLastTemplateRunnable(() -> {
enterWorkspace(selectAndOpenLastTemplateRunnable);
});
Runnable createNewTemplateRunnable = pageModel.getCreateNewTemplateRunnable();
pageModel.setCreateNewTemplateRunnable(() -> {
enterWorkspace(createNewTemplateRunnable);
});
Runnable openEmptyTemplateRunnable = pageModel.getOpenEmptyTemplateRunnable();
pageModel.setOpenEmptyTemplateRunnable(() -> {
enterWorkspace(openEmptyTemplateRunnable);
});
}
private void enterWorkspace(Runnable action) {
UIUtil.invokeAndWaitIfNeeded(() -> {
// 必须直接初始化
// 见 https://work.fineres.com/browse/REPORT-85293
StartupLoadingPanel loadingPanel = new StartupLoadingPanel(this);
loadingPanel.show();
setEnabled(false);
SwingWorker<Void, Void> task = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
action.run();
return null;
}
@Override
protected void done() {
try {
Void result = get();
setVisible(false);
} catch (Exception e) {
// 处理错误
UIUtil.invokeLaterIfNeeded(() -> {
UIExpandDialog.Builder()
.owner(StartupPageWindow.this)
.title(Toolkit.i18nText("Fine-Design_Basic_Remote_Env_Try"))
.message(Toolkit.i18nText("Fine-Design_Basic_Connection_Failed"))
.messageType(UIExpandDialog.WARNING_MESSAGE)
.detail(e.getMessage())
.expand(true)
.modal(false)
.build()
.setVisible(true);
setEnabled(true);
});
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
loadingPanel.hide();
}
}
};
task.execute();
});
}
private JPanel generateRecentOpenPanel(StartupPageModel pageModel) {
JPanel recentOpenPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), StartupPageConstants.ARC_DIAMETER, StartupPageConstants.ARC_DIAMETER);
}
};
recentOpenPanel.setLayout(new BorderLayout());
recentOpenPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 6));
StartupWorkspaceBean workspaceInfo = pageModel.getSelectWorkspaceInfo();
JPanel workspaceWrapperYPanel = new JPanel();
workspaceWrapperYPanel.setName("workspace-wrapper");
{
workspaceWrapperYPanel.setLayout(new VerticalFlowLayout());
JPanel workspaceWrapperXPanel = new JPanel();
workspaceWrapperXPanel.setLayout(new FlowLayout());
workspaceWrapperXPanel.setBorder(BorderFactory.createEmptyBorder());
JPanel workspacePanel = new JPanel();
workspacePanel.setLayout(new BorderLayout(0, 15));
UILabel workspaceIcon = new UILabel(StartupPageUtil.getIcon4RecentAreaByWorkspace(workspaceInfo));
workspacePanel.add(workspaceIcon, BorderLayout.NORTH);
UILabel nameLabel = new UILabel(workspaceInfo.getName());
nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
workspacePanel.add(nameLabel, BorderLayout.SOUTH);
workspaceWrapperXPanel.add(workspacePanel);
Dimension preferredSize = workspaceWrapperXPanel.getPreferredSize();
workspaceWrapperXPanel.setPreferredSize(new Dimension(WORKSPACE_PANEL_WIDTH, (int) preferredSize.getHeight()));
workspaceWrapperYPanel.add(workspaceWrapperXPanel);
}
recentOpenPanel.add(workspaceWrapperYPanel, BorderLayout.WEST);
JPanel separatorPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
{
JSeparator sep = new JSeparator();
sep.setOrientation(JSeparator.VERTICAL);
sep.setForeground(SEP_COLOR);
separatorPanel.add(sep, BorderLayout.CENTER);
}
recentOpenPanel.add(separatorPanel, BorderLayout.CENTER);
JComponent recentOpenGroupPanel = generateRecentOpenGroupPanel(pageModel, workspaceInfo);
recentOpenPanel.add(recentOpenGroupPanel, BorderLayout.EAST);
ColorUtils.syncBackground(recentOpenPanel, Color.WHITE);
Dimension preferredSize = recentOpenPanel.getPreferredSize();
recentOpenPanel.setPreferredSize(new Dimension(StartupPageConstants.CONTENT_WIDTH, (int) preferredSize.getHeight()));
JPanel recentOpenWrapperPanel = new JPanel();
recentOpenWrapperPanel.setName("recentOpenWrapper");
recentOpenWrapperPanel.setLayout(new BorderLayout(0, 0));
recentOpenWrapperPanel.setBorder(new EmptyBorder(0, 0, 0, 20));
recentOpenWrapperPanel.add(recentOpenPanel, BorderLayout.CENTER);
ColorUtils.syncBackgroundIfAbsent(recentOpenWrapperPanel, new Color(0,0,0,0), ThemeUtils.BACK_COLOR);
return recentOpenWrapperPanel;
}
@NotNull
private JComponent generateRecentOpenGroupPanel(StartupPageModel pageModel, StartupWorkspaceBean workspaceInfo) {
JPanel recentOpenGroupPanel = new JPanel();
Map<String, List<String>> recentFilesMap = pageModel.getRecentFilesMap();
boolean needScroll = false;
double itemHeight = 0.0d;
if (!CollectionUtils.isEmpty(recentFilesMap)) {
String name = workspaceInfo.getName();
List<String> recentFiles = recentFilesMap.get(name);
if (!CollectionUtils.isEmpty(recentFiles)) {
recentOpenGroupPanel.setLayout(new GridLayout(recentFiles.size(), 1, 50, 5));
needScroll = recentFiles.size() > RECENT_FILE_LIMIT;
for (String recentFile : recentFiles) {
JPanel recentItemPanel = new JPanel();
recentItemPanel.setLayout(new FlowLayout(FlowLayout.LEFT, ITEM_VERTICAL_GAP, 0));
recentItemPanel.add(new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/cpt")));
UILabel recentFileLabel = new UILabel(recentFile);
Color recentFileLabelForeground = recentFileLabel.getForeground();
recentItemPanel.add(recentFileLabel);
recentItemPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
recentFileLabel.setForeground(HOVER_COLOR);
StartupPageUtil.repaintAll(recentOpenGroupPanel);
}
@Override
public void mouseExited(MouseEvent e) {
recentFileLabel.setForeground(recentFileLabelForeground);
StartupPageUtil.repaintAll(recentOpenGroupPanel);
}
@Override
public void mouseClicked(MouseEvent e) {
doOpenLastTemplateAction(recentFile, pageModel);
}
});
Dimension preferredSize = recentItemPanel.getPreferredSize();
itemHeight = preferredSize.getHeight();
recentOpenGroupPanel.add(recentItemPanel);
}
}
}
Dimension preferredSize = recentOpenGroupPanel.getPreferredSize();
recentOpenGroupPanel.setPreferredSize(new Dimension(GROUP_WIDTH, (int) preferredSize.getHeight()));
if (needScroll) {
int scrollHeight = (int) Math.round(itemHeight * RECENT_FILE_LIMIT + ITEM_VERTICAL_GAP * (RECENT_FILE_LIMIT));
UIScrollPane scrollPane = new UIScrollPane(recentOpenGroupPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
scrollPane.setPreferredSize(new Dimension(GROUP_WIDTH, scrollHeight));
return scrollPane;
}
return recentOpenGroupPanel;
}
private StartupPageWorkspacePanel generateWorkspacePanel(StartupPageModel pageModel) {
StartupPageWorkspacePanel startupPageWorkspacePanel = new StartupPageWorkspacePanel(pageModel);
ColorUtils.syncBackgroundIfAbsent(startupPageWorkspacePanel, new Color(0, 0, 0, 0), ThemeUtils.BACK_COLOR);
return startupPageWorkspacePanel;
}
protected LayoutManager getCenterLayout(JComponent centerBody) {
return FRGUIPaneFactory.createCenterLayout(centerBody);
}
private void doOpenLastTemplateAction(String recentFile, StartupPageModel pageModel) {
DesignerEnvManager.getEnvManager().setLastOpenFile(recentFile);
pageModel.getOpenLastTemplateRunnable().run();
DesignerMetrics designerMetrics = DesignerStartupContext.getInstance().getDesignerMetrics();
designerMetrics.getStatistic().recordOpenLastTemplate(recentFile);
}
}