1 package be
.nikiroo
.fanfix_swing
.gui
.browser
;
3 import java
.awt
.BorderLayout
;
4 import java
.awt
.Component
;
5 import java
.awt
.event
.ActionEvent
;
6 import java
.awt
.event
.ActionListener
;
7 import java
.util
.ArrayList
;
11 import javax
.swing
.JPanel
;
12 import javax
.swing
.JScrollPane
;
13 import javax
.swing
.JTree
;
14 import javax
.swing
.SwingWorker
;
15 import javax
.swing
.UIDefaults
;
16 import javax
.swing
.event
.TreeSelectionEvent
;
17 import javax
.swing
.event
.TreeSelectionListener
;
18 import javax
.swing
.plaf
.TreeUI
;
19 import javax
.swing
.plaf
.basic
.BasicTreeUI
;
20 import javax
.swing
.tree
.DefaultMutableTreeNode
;
21 import javax
.swing
.tree
.DefaultTreeCellRenderer
;
22 import javax
.swing
.tree
.DefaultTreeModel
;
23 import javax
.swing
.tree
.TreeCellRenderer
;
24 import javax
.swing
.tree
.TreePath
;
26 import be
.nikiroo
.fanfix
.Instance
;
27 import be
.nikiroo
.fanfix_swing
.gui
.SearchBar
;
28 import be
.nikiroo
.fanfix_swing
.gui
.utils
.TreeCellSpanner
;
29 import be
.nikiroo
.fanfix_swing
.gui
.utils
.UiHelper
;
30 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
;
31 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
.Icon
;
32 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
.Size
;
34 public abstract class BasicTab
<T
> extends JPanel
{
35 private int totalCount
= 0;
36 private List
<String
> selectedElements
= new ArrayList
<String
>();
38 private String baseTitle
;
39 private String listenerCommand
;
43 private SearchBar searchBar
;
45 public BasicTab(int index
, String listenerCommand
) {
46 setLayout(new BorderLayout());
49 this.listenerCommand
= listenerCommand
;
51 data
= createEmptyData();
54 final DefaultMutableTreeNode root
= new DefaultMutableTreeNode();
56 tree
= new JTree(root
);
57 tree
.setUI(new BasicTreeUI());
58 TreeCellSpanner spanner
= new TreeCellSpanner(tree
, generateCellRenderer());
59 tree
.setCellRenderer(spanner
);
60 tree
.setRootVisible(false);
61 tree
.setShowsRootHandles(false);
63 tree
.addTreeSelectionListener(new TreeSelectionListener() {
65 public void valueChanged(TreeSelectionEvent e
) {
66 List
<String
> elements
= new ArrayList
<String
>();
67 TreePath
[] paths
= tree
.getSelectionPaths();
69 for (TreePath path
: paths
) {
70 String key
= path
.getLastPathComponent().toString();
71 elements
.add(keyToElement(key
));
75 List
<String
> selectedElements
= new ArrayList
<String
>();
76 for (String element
: elements
) {
77 if (!selectedElements
.contains(element
)) {
78 selectedElements
.add(element
);
82 BasicTab
.this.selectedElements
= selectedElements
;
84 fireActionPerformed();
88 add(UiHelper
.scroll(tree
), BorderLayout
.CENTER
);
90 searchBar
= new SearchBar();
91 add(searchBar
, BorderLayout
.NORTH
);
92 searchBar
.addActionListener(new ActionListener() {
94 public void actionPerformed(ActionEvent e
) {
95 root
.removeAllChildren();
96 loadData(root
, data
, searchBar
.getText());
97 ((DefaultTreeModel
) tree
.getModel()).reload();
98 fireActionPerformed();
102 SwingWorker
<Map
<String
, List
<String
>>, Integer
> worker
= new SwingWorker
<Map
<String
, List
<String
>>, Integer
>() {
104 protected Map
<String
, List
<String
>> doInBackground() throws Exception
{
105 return Instance
.getInstance().getLibrary().getSourcesGrouped();
109 protected void done() {
111 root
.removeAllChildren();
112 totalCount
= loadData(root
, data
, searchBar
.getText());
113 ((DefaultTreeModel
) tree
.getModel()).reload();
115 fireActionPerformed();
122 * The currently selected elements, or an empty list.
124 * @return the sources (cannot be NULL)
126 public List
<String
> getSelectedElements() {
127 return selectedElements
;
130 public int getTotalCount() {
134 public String
getBaseTitle() {
138 public void setBaseTitle(String baseTitle
) {
139 this.baseTitle
= baseTitle
;
142 public String
getTitle() {
143 String title
= getBaseTitle();
145 if (totalCount
> 0) {
146 int selected
= selectedElements
.size();
147 count
= " (" + (selected
> 0 ? selected
+ "/" : "") + totalCount
+ ")";
150 return title
+ count
;
153 public int getIndex() {
157 public void unselect() {
158 tree
.clearSelection();
162 * Adds the specified action listener to receive action events from this
165 * @param listener the action listener to be added
167 public synchronized void addActionListener(ActionListener listener
) {
168 listenerList
.add(ActionListener
.class, listener
);
172 * Removes the specified action listener so that it no longer receives action
173 * events from this {@link SearchBar}.
175 * @param listener the action listener to be removed
177 public synchronized void removeActionListener(ActionListener listener
) {
178 listenerList
.remove(ActionListener
.class, listener
);
182 * Notify the listeners of an action.
184 protected void fireActionPerformed() {
185 ActionEvent e
= new ActionEvent(this, ActionEvent
.ACTION_PERFORMED
, listenerCommand
);
186 Object
[] listeners
= listenerList
.getListenerList();
187 for (int i
= listeners
.length
- 2; i
>= 0; i
-= 2) {
188 if (listeners
[i
] == ActionListener
.class) {
189 ((ActionListener
) listeners
[i
+ 1]).actionPerformed(e
);
194 protected boolean checkFilter(String filter
, String value
) {
195 return (filter
== null || filter
.isEmpty() || value
.toLowerCase().contains(filter
.toLowerCase()));
198 protected boolean checkFilter(String filter
, List
<String
> list
) {
199 for (String value
: list
) {
200 if (checkFilter(filter
, value
))
206 protected abstract T
createEmptyData();
208 protected abstract void fillData(T data
);
210 protected abstract String
keyToElement(String key
);
212 protected abstract String
keyToDisplay(String key
);
214 protected abstract int loadData(DefaultMutableTreeNode root
, T data
, String filter
);
216 private TreeCellRenderer
generateCellRenderer() {
217 DefaultTreeCellRenderer renderer
= new DefaultTreeCellRenderer() {
219 public Component
getTreeCellRendererComponent(JTree tree
, Object value
, boolean selected
, boolean expanded
,
220 boolean leaf
, int row
, boolean hasFocus
) {
221 if (value
instanceof DefaultMutableTreeNode
) {
222 if (((DefaultMutableTreeNode
) value
).getLevel() > 1) {
224 setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x4
));
226 setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x16
));
230 String display
= value
== null ?
"" : value
.toString();
231 if (!display
.isEmpty())
232 display
= keyToDisplay(display
);
234 return super.getTreeCellRendererComponent(tree
, display
, selected
, expanded
, leaf
, row
, hasFocus
);
238 renderer
.setClosedIcon(IconGenerator
.get(Icon
.arrow_right
, Size
.x16
));
239 renderer
.setOpenIcon(IconGenerator
.get(Icon
.arrow_down
, Size
.x16
));
240 renderer
.setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x16
));