1
22 package org.crosswire.bibledesktop.book;
23
24 import java.awt.Component;
25 import java.awt.FlowLayout;
26 import java.awt.event.ActionEvent;
27 import java.awt.event.ActionListener;
28 import java.awt.event.ItemEvent;
29 import java.awt.event.ItemListener;
30 import java.io.IOException;
31 import java.io.ObjectInputStream;
32 import java.util.ArrayList;
33 import java.util.Comparator;
34 import java.util.List;
35
36 import javax.swing.JButton;
37 import javax.swing.JComboBox;
38 import javax.swing.JPanel;
39 import javax.swing.event.EventListenerList;
40
41 import org.crosswire.bibledesktop.BDMsg;
42 import org.crosswire.common.swing.ActionFactory;
43 import org.crosswire.common.swing.CWAction;
44 import org.crosswire.common.swing.GuiUtil;
45 import org.crosswire.jsword.book.Book;
46 import org.crosswire.jsword.book.BookFilter;
47 import org.crosswire.jsword.book.BookProvider;
48
49
56 public class ParallelBookPicker extends JPanel implements BookProvider {
57
58
66 public ParallelBookPicker(BookFilter filter, Comparator<Book> comparator) {
67 this.filter = filter;
68 this.comparator = comparator;
69 initialize();
70 }
71
72
75 private void initialize() {
76 setLayout(new FlowLayout(FlowLayout.LEADING, 1, 1));
77 listeners = new EventListenerList();
78 actions = new ActionFactory(this);
79
80 JPanel buttonBox = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
81
82 CWAction action = actions.addAction("RemovePicker");
83 action.setTooltip(BDMsg.gettext("Remove a parallel Bible"));
86 action.setSmallIcon("images/subtract-13.png");
87 buttonBox.add(GuiUtil.flatten(new JButton(action)));
88
89 action = actions.addAction("AddPicker");
90 action.setTooltip(BDMsg.gettext("Add a parallel Bible"));
93 action.setSmallIcon("images/add-13.png");
94 buttonBox.add(GuiUtil.flatten(new JButton(action)));
95 add(buttonBox);
96
97 doAddPicker();
99 }
100
101
104 public void doAddPicker() {
105 BooksComboBoxModel mdlBook = new BooksComboBoxModel(filter, comparator);
106 JComboBox cboBook = new JComboBox(mdlBook);
107 cboBook.setPrototypeDisplayValue(BookListCellRenderer.PROTOTYPE_BOOK_NAME);
108 cboBook.setRenderer(new BookListCellRenderer(true));
109 cboBook.addItemListener(new SelectedItemListener(this));
110 cboBook.addActionListener(new SelectedActionListener());
111 add(cboBook);
112
113 Book book = mdlBook.getSelectedBook();
114 if (book != null) {
115 cboBook.setToolTipText(book.getName());
116 }
117
118 enableButtons();
119 GuiUtil.applyDefaultOrientation(this);
120 GuiUtil.refresh(this);
121 fireBooksChosen(new BookSelectEvent(this));
122 }
123
124
127 public void doRemovePicker() {
128 int size = getComponentCount();
131 if (size > 2) {
132 remove(size - 1);
133 enableButtons();
134 GuiUtil.refresh(this);
135 fireBooksChosen(new BookSelectEvent(this));
136 }
137
138 }
139
140
143 public Book[] getBooks() {
144 List<Book> books = new ArrayList<Book>();
145 int count = getComponentCount();
146 for (int i = 1; i < count; i++) {
147 Component comp = getComponent(i);
148 if (comp instanceof JComboBox) {
149 JComboBox combo = (JComboBox) comp;
150 Book book = (Book) combo.getSelectedItem();
151 if (book != null) {
152 books.add(book);
153 }
154 }
155 }
156 return books.toArray(new Book[books.size()]);
157 }
158
159
162 public Book getFirstBook() {
163 int count = getComponentCount();
164 for (int i = 1; i < count; i++) {
165 Component comp = getComponent(i);
166 if (comp instanceof JComboBox) {
167 JComboBox combo = (JComboBox) comp;
168 return (Book) combo.getSelectedItem();
169 }
170 }
171 return null;
172 }
173
174
177 public static int getMaxPickers() {
178 return maxPickers;
179 }
180
181
185 public static void setMaxPickers(int maxPickers) {
186 ParallelBookPicker.maxPickers = maxPickers;
187 }
188
189
192 public synchronized void addBookListener(BookSelectListener li) {
193 listeners.add(BookSelectListener.class, li);
194 }
195
196
199 public synchronized void removeBookListener(BookSelectListener li) {
200 listeners.remove(BookSelectListener.class, li);
201 }
202
203
206 protected void fireBooksChosen(BookSelectEvent ev) {
207 Object[] contents = listeners.getListenerList();
209
210 for (int i = contents.length - 2; i >= 0; i -= 2) {
213 if (contents[i] == BookSelectListener.class) {
214 ((BookSelectListener) contents[i + 1]).booksChosen(ev);
215 }
216 }
217 }
218
219 public void enableButtons() {
220 int count = getComponentCount() - 1;
221 actions.findAction("RemovePicker").setEnabled(count > 1);
222 actions.findAction("AddPicker").setEnabled(count < maxPickers);
223 getComponent(0).setVisible(maxPickers >= 2 || count > maxPickers);
224 }
225
226
233 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
234 filter = null;
235 comparator = null;
236 listeners = new EventListenerList();
237 actions = new ActionFactory(this);
238
239 is.defaultReadObject();
240 }
241
242
246 final class SelectedItemListener implements ItemListener, BookProvider {
247 SelectedItemListener(ParallelBookPicker picker) {
248 this.picker = picker;
249 }
250
251
254 public void itemStateChanged(ItemEvent ev) {
255 if (ev.getStateChange() == ItemEvent.SELECTED) {
256 JComboBox combo = (JComboBox) ev.getSource();
257
258 Book selected = (Book) combo.getSelectedItem();
259
260 fireBooksChosen(new BookSelectEvent(this));
261 combo.setToolTipText(selected.getName());
262 }
263 }
264
265
268 public Book[] getBooks() {
269 return picker.getBooks();
270 }
271
272
275 public Book getFirstBook() {
276 return picker.getFirstBook();
277 }
278
279 private ParallelBookPicker picker;
280 }
281
282
285 static final class SelectedActionListener implements ActionListener {
286
289 public void actionPerformed(ActionEvent e) {
290 JComboBox cbo = (JComboBox) e.getSource();
291 if (cbo.getSelectedIndex() == -1 && cbo.getItemCount() > 0) {
292 cbo.setSelectedIndex(0);
293 }
294 }
295 }
296
297
300 private transient BookFilter filter;
301
302
305 private transient Comparator<Book> comparator;
306
307
310 private transient ActionFactory actions;
311
312
315 private transient EventListenerList listeners;
316
317
320 private static final int MAX_PICKERS = 5;
321
322
325 private static int maxPickers = MAX_PICKERS;
326
327
330 private static final long serialVersionUID = 1633401996774729671L;
331 }
332