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
.JTree
;
12 import javax
.swing
.SwingWorker
;
13 import javax
.swing
.event
.TreeSelectionEvent
;
14 import javax
.swing
.event
.TreeSelectionListener
;
15 import javax
.swing
.plaf
.basic
.BasicTreeUI
;
16 import javax
.swing
.tree
.DefaultMutableTreeNode
;
17 import javax
.swing
.tree
.DefaultTreeCellRenderer
;
18 import javax
.swing
.tree
.DefaultTreeModel
;
19 import javax
.swing
.tree
.TreeCellRenderer
;
20 import javax
.swing
.tree
.TreePath
;
22 import be
.nikiroo
.fanfix_swing
.gui
.SearchBar
;
23 import be
.nikiroo
.fanfix_swing
.gui
.utils
.ListenerPanel
;
24 import be
.nikiroo
.fanfix_swing
.gui
.utils
.TreeCellSpanner
;
25 import be
.nikiroo
.fanfix_swing
.gui
.utils
.TreeSnapshot
;
26 import be
.nikiroo
.fanfix_swing
.gui
.utils
.UiHelper
;
27 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
;
28 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
.Icon
;
29 import be
.nikiroo
.fanfix_swing
.images
.IconGenerator
.Size
;
31 public abstract class BasicTab
<T
> extends ListenerPanel
{
32 private int totalCount
= 0;
33 private List
<String
> selectedElements
= new ArrayList
<String
>();
35 private String baseTitle
;
36 private String listenerCommand
;
40 private DefaultMutableTreeNode root
;
41 private SearchBar searchBar
;
43 public BasicTab(int index
, String listenerCommand
) {
44 setLayout(new BorderLayout());
47 this.listenerCommand
= listenerCommand
;
49 data
= createEmptyData();
52 root
= new DefaultMutableTreeNode();
54 tree
= new JTree(root
);
55 tree
.setUI(new BasicTreeUI());
56 TreeCellSpanner spanner
= new TreeCellSpanner(tree
, generateCellRenderer());
57 tree
.setCellRenderer(spanner
);
58 tree
.setRootVisible(false);
59 tree
.setShowsRootHandles(false);
61 tree
.addTreeSelectionListener(new TreeSelectionListener() {
63 public void valueChanged(TreeSelectionEvent e
) {
64 List
<String
> elements
= new ArrayList
<String
>();
65 TreePath
[] paths
= tree
.getSelectionPaths();
67 for (TreePath path
: paths
) {
68 String key
= path
.getLastPathComponent().toString();
69 elements
.add(keyToElement(key
));
73 List
<String
> selectedElements
= new ArrayList
<String
>();
74 for (String element
: elements
) {
75 if (!selectedElements
.contains(element
)) {
76 selectedElements
.add(element
);
80 BasicTab
.this.selectedElements
= selectedElements
;
82 fireActionPerformed(BasicTab
.this.listenerCommand
);
86 add(UiHelper
.scroll(tree
), BorderLayout
.CENTER
);
88 searchBar
= new SearchBar();
89 add(searchBar
, BorderLayout
.NORTH
);
90 searchBar
.addActionListener(new ActionListener() {
92 public void actionPerformed(ActionEvent e
) {
100 public void reloadData() {
101 final TreeSnapshot snapshot
= new TreeSnapshot(tree
);
102 SwingWorker
<Map
<String
, List
<String
>>, Integer
> worker
= new SwingWorker
<Map
<String
, List
<String
>>, Integer
>() {
104 protected Map
<String
, List
<String
>> doInBackground() throws Exception
{
110 protected void done() {
113 } catch (Exception e
) {
117 // TODO: update is flickering...
119 root
.removeAllChildren();
120 totalCount
= loadData(root
, data
, searchBar
.getText());
121 ((DefaultTreeModel
) tree
.getModel()).reload();
125 fireActionPerformed(listenerCommand
);
132 * The currently selected elements, or an empty list.
134 * @return the sources (cannot be NULL)
136 public List
<String
> getSelectedElements() {
137 return selectedElements
;
140 public int getTotalCount() {
144 public String
getBaseTitle() {
148 public void setBaseTitle(String baseTitle
) {
149 this.baseTitle
= baseTitle
;
152 public String
getTitle() {
153 String title
= getBaseTitle();
155 if (totalCount
> 0) {
156 int selected
= selectedElements
.size();
157 count
= " (" + (selected
> 0 ? selected
+ "/" : "") + totalCount
+ ")";
160 return title
+ count
;
163 public int getIndex() {
167 public void unselect() {
168 tree
.clearSelection();
171 protected boolean checkFilter(String filter
, String value
) {
172 return (filter
== null || filter
.isEmpty() || value
.toLowerCase().contains(filter
.toLowerCase()));
175 protected boolean checkFilter(String filter
, List
<String
> list
) {
176 for (String value
: list
) {
177 if (checkFilter(filter
, value
))
183 protected abstract T
createEmptyData();
185 protected abstract void fillData(T data
);
187 protected abstract String
keyToElement(String key
);
189 protected abstract String
keyToDisplay(String key
);
191 protected abstract int loadData(DefaultMutableTreeNode root
, T data
, String filter
);
193 private TreeCellRenderer
generateCellRenderer() {
194 DefaultTreeCellRenderer renderer
= new DefaultTreeCellRenderer() {
196 public Component
getTreeCellRendererComponent(JTree tree
, Object value
, boolean selected
, boolean expanded
,
197 boolean leaf
, int row
, boolean hasFocus
) {
198 if (value
instanceof DefaultMutableTreeNode
) {
199 if (((DefaultMutableTreeNode
) value
).getLevel() > 1) {
201 setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x4
));
203 setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x16
));
207 String display
= value
== null ?
"" : value
.toString();
208 if (!display
.isEmpty())
209 display
= keyToDisplay(display
);
211 return super.getTreeCellRendererComponent(tree
, display
, selected
, expanded
, leaf
, row
, hasFocus
);
215 renderer
.setClosedIcon(IconGenerator
.get(Icon
.arrow_right
, Size
.x16
));
216 renderer
.setOpenIcon(IconGenerator
.get(Icon
.arrow_down
, Size
.x16
));
217 renderer
.setLeafIcon(IconGenerator
.get(Icon
.empty
, Size
.x16
));