diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/FineBreadcrumbPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/FineBreadcrumbPane.java new file mode 100644 index 0000000000..29313ca232 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/FineBreadcrumbPane.java @@ -0,0 +1,153 @@ +package com.fr.design.gui.frpane; + +import com.fine.swing.ui.layout.Row; +import com.fine.theme.utils.FineUIScale; +import com.fine.theme.utils.FineUIStyle; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.file.FILE; +import com.fr.general.ComparatorUtils; + +import javax.swing.BorderFactory; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Insets; + +public class FineBreadcrumbPane extends Row { + + private static final int SEP_HEIGHT = 20; + + private static final int BUTTON_HEIGHT = 20; + + private static final int MAX_BUTTON_WIDTH = FineUIScale.scale(150); + + private BreadcrumbButton currentCrumb; + + public void setRootButton(T text, final BreadcrumbBackListener backListener) { + clear(); + currentCrumb = new BreadcrumbButton<>(getText(text), text); + add(currentCrumb); + final int index = getComponentCount(); + addBreadcrumbListener(currentCrumb, index, backListener); + repaint(); + + } + + public void addCrumb(final T text, final BreadcrumbBackListener backListener) { + if (currentCrumb != null) { + if (text instanceof FILE) { + FILE file = (FILE) text; + if (ComparatorUtils.equals(currentCrumb.getContent(), file) || !file.isDirectory()) { + return; + } + if (file.getParent().equals(((FILE)currentCrumb.getContent()).getParent())) { + remove(currentCrumb); + currentCrumb = new BreadcrumbButton<>(getText(text), text); + final int index = getComponentCount(); + addBreadcrumbListener(currentCrumb, index, backListener); + repaint(); + return; + } + } + currentCrumb.setSelected(false); + currentCrumb.setForeground(Color.GRAY); + add(createSeparator()); + } + final BreadcrumbButton breadcrumb = createBreadcrumb(text); + add(breadcrumb); + currentCrumb = breadcrumb; + final int index = getComponentCount(); + addBreadcrumbListener(breadcrumb, index, backListener); + } + + private void removeTailCrumbs(int from) { + Component[] components = getComponents(); + for (int i = from; i < components.length; i++) { + remove(components[i]); + } + currentCrumb = (BreadcrumbButton) components[from-1]; + revalidate(); + repaint(); + } + + public void clear() { + removeAll(); + currentCrumb = null; + } + + protected Component createSeparator() { + UILabel separator = new UILabel("/"); + separator.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2)); + separator.setPreferredSize(new Dimension(separator.getPreferredSize().width, FineUIScale.scale(SEP_HEIGHT))); + + return separator; + } + + protected BreadcrumbButton createBreadcrumb(T content) { + BreadcrumbButton button = new BreadcrumbButton(getText(content), content); + button.setPreferredSize(new Dimension(Math.min(button.getPreferredSize().width, MAX_BUTTON_WIDTH), FineUIScale.scale(BUTTON_HEIGHT))); + button.setSelected(true); + button.setForeground(Color.black); + return button; + } + + private void addBreadcrumbListener(BreadcrumbButton breadcrumb, int index, BreadcrumbBackListener backListener) { + breadcrumb.addActionListener(e -> { + removeTailCrumbs(index); + breadcrumb.setSelected(true); + breadcrumb.setForeground(Color.BLACK); + if (breadcrumb != currentCrumb) { + currentCrumb = breadcrumb; + } + if (backListener != null) { + backListener.onBreadcrumbBack(breadcrumb.getContent()); + } + }); + } + + private String getText(T text) { + if (text instanceof String) { + return (String) text; + } else if (text instanceof FILE){ + return ((FILE)text).getName(); + } + return (String) text; + } + + public static class BreadcrumbButton extends UIButton { + + private T content; + + public BreadcrumbButton(String text, T content) { + super(text); + BreadcrumbButton.this.content = content; + setMargin(new Insets(0, 0, 0, 0)); + setBorder(BorderFactory.createEmptyBorder()); + FineUIStyle.setStyle(BreadcrumbButton.this, FineUIStyle.PLAIN_BUTTON); + setBorderPainted(false); + setOpaque(false); + } + + @Override + public Insets getMargin() { + Insets insets = super.getMargin(); + if (insets != null) { + insets.set(0, 0, 0, 0); + } + return insets; + } + + protected T getContent() { + return content; + } + + protected void setContent(T content) { + this.content = content; + } + } + + public interface BreadcrumbBackListener { + void onBreadcrumbBack(T text); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java index 704f9c1a35..720e5db8bc 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java @@ -12,6 +12,7 @@ import com.fr.design.dialog.BasicPane; import com.fr.design.event.ChangeEvent; import com.fr.design.event.ChangeListener; import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.FineBreadcrumbPane; import com.fr.design.gui.frpane.FineTabbedPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.i18n.Toolkit; @@ -53,7 +54,7 @@ import java.util.Set; */ public class TemplateThemeGridPagesPane extends JPanel { public static final String COMPLETE_BUTTON = "theme_button_complete"; - private BreadcrumbBar breadcrumbBar; + private FineBreadcrumbPane breadcrumbBar; private JPanel contentPane; private CardLayout cardLayout; @@ -75,7 +76,7 @@ public class TemplateThemeGridPagesPane extends JPanel { setLayout(new BorderLayout()); setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); - breadcrumbBar = new BreadcrumbBar(); + breadcrumbBar = new FineBreadcrumbPane(); breadcrumbBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); add(breadcrumbBar, BorderLayout.NORTH); @@ -104,14 +105,11 @@ public class TemplateThemeGridPagesPane extends JPanel { pageChangeListener.onPageChangeListener(); } breadcrumbBar.clear(); - breadcrumbBar.addCrumb(themeUsingPane.getTitle(), new BreadcrumbBar.BreadcrumbBackListener() { - @Override - public void onBreadcrumbBack(String text) { - cardLayout.show(contentPane, themeUsingPane.getTitle()); - currentTemplateThemeGridPagePane = themeUsingPane; - if (pageChangeListener != null) { - pageChangeListener.onPageChangeListener(); - } + breadcrumbBar.addCrumb(themeUsingPane.getTitle(), text -> { + cardLayout.show(contentPane, themeUsingPane.getTitle()); + currentTemplateThemeGridPagePane = themeUsingPane; + if (pageChangeListener != null) { + pageChangeListener.onPageChangeListener(); } }); } diff --git a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java index 5830f16d9a..023d7d2854 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -18,6 +18,7 @@ import com.fr.design.env.DesignerWorkspaceType; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.NodeAuthProcessor; import com.fr.design.fun.ReportSupportedFileUIProvider; +import com.fr.design.gui.frpane.FineBreadcrumbPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButtonUI; import com.fr.design.gui.icombobox.UIComboBox; @@ -154,6 +155,7 @@ public class FILEChooserPane extends BasicPane { private FILEFilter filter; private LocationButtonPane locationBtnPane; // 显示location的Panel + private FineBreadcrumbPane locationBreadcrumbPane; private UIButton mkdirButton; private JList placesList; // File.listRoots() + Env + Favourite @@ -305,7 +307,7 @@ public class FILEChooserPane extends BasicPane { JPanel locationPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); // locationPane.setLayout(FRGUIPaneFactory.createBorderLayout()); - locationPane.add(locationBtnPane = new LocationButtonPane(), BorderLayout.CENTER); + locationPane.add(locationBreadcrumbPane = new FineBreadcrumbPane(), BorderLayout.CENTER); mkdirButton = initMkdirButton(); locationPane.add(mkdirButton, BorderLayout.EAST); @@ -348,6 +350,9 @@ public class FILEChooserPane extends BasicPane { Object selValue = placesList.getSelectedValue(); if (selValue instanceof FILE) { setSelectedDirectory((FILE) selValue); + locationBreadcrumbPane.setRootButton(selValue, text -> { + setSelectedDirectory((FILE) selValue); + }); } } }); @@ -418,6 +423,9 @@ public class FILEChooserPane extends BasicPane { setFileTextField((FILE) selValue); fileNameTextField.addDocumentListener(); } else { + locationBreadcrumbPane.addCrumb(selValue, text -> { + setSelectedDirectory((FILE) selValue); + }); setSelectedDirectory((FILE) selValue); if (!((FILE) selValue).isDirectory()) { doOK(); @@ -566,7 +574,7 @@ public class FILEChooserPane extends BasicPane { } private void doCancel() { - this.locationBtnPane.setPopDir(null); + //this.locationBtnPane.setPopDir(null); dialogExit(); } @@ -1096,7 +1104,9 @@ public class FILEChooserPane extends BasicPane { } private void setTopPath(String path) { - this.locationBtnPane.setTopPath(path); + this.locationBreadcrumbPane.setRootButton(path, text -> { + //setSelectedDirectory(text); + }); } @@ -1161,8 +1171,6 @@ public class FILEChooserPane extends BasicPane { } currentDirectory = dir; - - this.locationBtnPane.populate(currentDirectory); this.mkdirButton.setEnabled(currentDirectory != null); refreshSubFileListModel();