3 changed files with 174 additions and 15 deletions
@ -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 <T> 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<T> 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<T> 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 <T> 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 <T> { |
||||||
|
void onBreadcrumbBack(T text); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue