1
22 package org.crosswire.bibledesktop.passage;
23
24 import java.awt.BorderLayout;
25 import java.awt.FlowLayout;
26 import java.io.IOException;
27 import java.io.ObjectInputStream;
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import javax.swing.JButton;
32 import javax.swing.JList;
33 import javax.swing.JPanel;
34 import javax.swing.JScrollPane;
35 import javax.swing.event.ListSelectionEvent;
36 import javax.swing.event.ListSelectionListener;
37
38 import org.crosswire.bibledesktop.BDMsg;
39 import org.crosswire.bibledesktop.book.DisplaySelectEvent;
40 import org.crosswire.bibledesktop.book.DisplaySelectListener;
41 import org.crosswire.common.swing.ActionFactory;
42 import org.crosswire.common.swing.CWAction;
43 import org.crosswire.common.swing.CWScrollPane;
44 import org.crosswire.common.swing.GuiUtil;
45 import org.crosswire.jsword.book.Book;
46 import org.crosswire.jsword.passage.Key;
47 import org.crosswire.jsword.passage.Passage;
48 import org.crosswire.jsword.passage.RestrictionType;
49 import org.crosswire.jsword.passage.VerseRange;
50
51
58 public class KeySidebar extends JPanel implements DisplaySelectListener, KeyChangeListener {
59
62 public KeySidebar(Book[] books) {
63 this.books = books == null ? null : (Book[]) books.clone();
64 init();
65 setActive();
66 }
67
68
71 private void init() {
72 setLayout(new BorderLayout());
73
74 model = new RangeListModel(RestrictionType.CHAPTER);
75
76 list = new JList(model);
77 list.addListSelectionListener(new ListSelectionListener() {
78 public void valueChanged(ListSelectionEvent ev) {
79 if (ev.getValueIsAdjusting()) {
80 return;
81 }
82
83 selection();
84 }
85 });
86
87 JScrollPane scroll = new CWScrollPane(list);
88
89 ActionFactory actions = new ActionFactory(this);
90
91 actDelete = actions.addAction("DeleteSelected");
92 actDelete.setTooltip(BDMsg.gettext("Remove the selected passages in the current passage list."));
94 actDelete.setSmallIcon("toolbarButtonGraphics/general/Remove16.gif");
95 actDelete.setLargeIcon("toolbarButtonGraphics/general/Remove24.gif");
96
97 actBlur1 = actions.addAction("Blur1");
98 actBlur1.setTooltip(BDMsg.gettext("Expand all or the selected passage by 1 verse."));
100 actBlur1.setSmallIcon("images/Blur1_16.gif");
101
102 actBlur5 = actions.addAction("Blur5");
103 actBlur5.setTooltip(BDMsg.gettext("Expand all or the selected passage by 5 verses."));
105 actBlur5.setSmallIcon("images/Blur5_16.gif");
106
107 JButton delete = new JButton(actDelete);
108 delete.setText(null);
110 JButton blur1 = new JButton(actBlur1);
111 blur1.setText(null);
112 JButton blur5 = new JButton(actBlur5);
114 blur5.setText(null);
115
117 JPanel mutate = new JPanel(new FlowLayout());
118 mutate.add(delete);
119 mutate.add(blur1);
120 mutate.add(blur5);
121
122 add(mutate, BorderLayout.NORTH);
123 add(scroll, BorderLayout.CENTER);
124 }
125
126
130 public void doBlur1() {
131 doBlur(1);
132 }
133
134
138 public void doBlur5() {
139 doBlur(5);
140 }
141
142
149 private void doBlur(int amount) {
150 Object[] objs = list.getSelectedValues();
152
153 Key copy = key.clone();
155
156 if (objs.length == 0) {
158 copy.blur(amount, RestrictionType.getDefaultBlurRestriction());
159 } else {
160 for (Object obj : objs) {
161 Key keyCopy = ((VerseRange) obj).clone();
162 keyCopy.blur(amount, RestrictionType.getDefaultBlurRestriction());
163 copy.addAll(keyCopy);
164 }
165 }
166 fireKeyChanged(new KeyChangeEvent(this, copy));
167
168 int total = model.getSize();
170 int count = objs.length;
171 for (int i = 0; i < total; i++) {
172 Key listedKey = (Key) model.getElementAt(i);
173
174 for (Object obj : objs) {
176 Key selectedKey = (VerseRange) obj;
177 if (listedKey.contains(selectedKey)) {
178 list.addSelectionInterval(i, i);
179 --count;
180 }
181 }
182
183 if (count <= 0) {
185 break;
186 }
187 }
188
189 GuiUtil.refresh(this);
190 }
191
192
195 public void doDeleteSelected() {
196 RangeListModel rlm = (RangeListModel) list.getModel();
197
198 Passage ref = rlm.getPassage();
199 Object[] selected = list.getSelectedValues();
200 for (int i = 0; i < selected.length; i++) {
201 VerseRange range = (VerseRange) selected[i];
202 ref.remove(range);
203 }
204
205 list.setSelectedIndices(new int[0]);
206
207 partial = null;
208 model.setPassage((Passage) key);
209 fireKeyChanged(new KeyChangeEvent(this, key));
210 setActive();
211 }
212
213 public Key getKey() {
214 return key;
215 }
216
217 private void setKey(Key newKey) {
218 if (partial != null && partial.equals(newKey)) {
219 return;
220 }
221
222 if (key != null && key.equals(newKey)) {
223 return;
224 }
225
226 if (newKey == null) {
231 key = null;
232 } else {
233 if (key != newKey) {
234 key = newKey.clone();
235 }
236 }
237 partial = null;
238 model.setPassage((Passage) key);
239 fireKeyChanged(new KeyChangeEvent(this, key));
240 setActive();
241 }
242
243
246 final void selection() {
247 Object[] selected = list.getSelectedValues();
248
249 if (selected.length > 0) {
250 partial = books[0].createEmptyKeyList();
251
252 for (int i = 0; i < selected.length; i++) {
253 partial.addAll((Key) selected[i]);
254 }
255
256 fireKeyChanged(new KeyChangeEvent(this, partial));
257 } else {
258 fireKeyChanged(new KeyChangeEvent(this, key));
260 }
261
262 setActive();
263 }
264
265
268 private void setActive() {
269 Object[] selected = list.getSelectedValues();
270
271 actDelete.setEnabled(selected.length != 0);
273 boolean blurable = model.getSize() != 0;
274 actBlur1.setEnabled(blurable);
275 actBlur5.setEnabled(blurable);
276 }
277
278
281 public void passageSelected(DisplaySelectEvent ev) {
282 setKey(ev.getKey());
283 }
284
285
288 public void bookChosen(DisplaySelectEvent ev) {
289 books = ev.getBookProvider().getBooks();
290 }
291
292
295 public void keyChanged(KeyChangeEvent ev) {
296 setKey(ev.getKey());
297 }
298
299
302 public synchronized void addKeyChangeListener(KeyChangeListener listener) {
303 List<KeyChangeListener> temp = new ArrayList<KeyChangeListener>(2);
304
305 if (keyChangeListeners != null) {
306 temp.addAll(keyChangeListeners);
307 }
308
309 if (!temp.contains(listener)) {
310 temp.add(listener);
311 keyChangeListeners = temp;
312 }
313 }
314
315
318 public synchronized void removeKeyChangeListener(KeyChangeListener listener) {
319 if (keyChangeListeners != null && keyChangeListeners.contains(listener)) {
320 List<KeyChangeListener> temp = new ArrayList<KeyChangeListener>();
321 temp.addAll(keyChangeListeners);
322
323 temp.remove(listener);
324 keyChangeListeners = temp;
325 }
326 }
327
328
331 final synchronized void fireKeyChanged(KeyChangeEvent ev) {
332 if (keyChangeListeners != null) {
333 for (KeyChangeListener li : keyChangeListeners) {
334 li.keyChanged(ev);
335 }
336 }
337 }
338
339
346 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
347 books = null;
349 keyChangeListeners = null;
350 is.defaultReadObject();
351 }
352
353
356 private Key key;
357
358
361 private Key partial;
362
363
366 private transient Book[] books;
367
368
371 private transient List<KeyChangeListener> keyChangeListeners;
372
373
376 private JList list;
377 private RangeListModel model;
378 private CWAction actDelete;
379 private CWAction actBlur1;
380 private CWAction actBlur5;
381
382
385 private static final long serialVersionUID = 3905241217179466036L;
386 }
387