1
22 package org.crosswire.bibledesktop.book;
23
24 import java.awt.BorderLayout;
25 import java.awt.Dimension;
26 import java.io.File;
27 import java.io.FileReader;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.Reader;
32 import java.io.Writer;
33
34 import javax.swing.JFileChooser;
35 import javax.swing.UIManager;
36 import javax.swing.event.EventListenerList;
37 import javax.swing.filechooser.FileFilter;
38
39 import org.crosswire.bibledesktop.BDMsg;
40 import org.crosswire.bibledesktop.display.BookDataDisplay;
41 import org.crosswire.bibledesktop.display.basic.SplitBookDataDisplay;
42 import org.crosswire.bibledesktop.display.basic.TabbedBookDataDisplay;
43 import org.crosswire.bibledesktop.passage.KeySidebar;
44 import org.crosswire.common.swing.GuiUtil;
45 import org.crosswire.common.swing.desktop.Clearable;
46 import org.crosswire.common.swing.desktop.TabbedPanePanel;
47 import org.crosswire.common.swing.desktop.Titleable;
48 import org.crosswire.common.swing.desktop.event.TitleChangedEvent;
49 import org.crosswire.common.swing.desktop.event.TitleChangedListener;
50 import org.crosswire.common.util.CWProject;
51 import org.crosswire.common.util.Logger;
52 import org.crosswire.common.util.Reporter;
53 import org.crosswire.jsword.passage.Key;
54 import org.crosswire.jsword.passage.NoSuchVerseException;
55 import org.crosswire.jsword.passage.Passage;
56 import org.crosswire.jsword.passage.PassageKeyFactory;
57
58
66 public class BibleViewPane extends TabbedPanePanel implements Titleable, Clearable, TitleChangedListener {
67
70 public BibleViewPane(boolean showSidebar) {
71 listeners = new EventListenerList();
72 pnlSelect = new DisplaySelectPane();
73 KeySidebar sidebar = new KeySidebar(pnlSelect.getBooks());
74 BookDataDisplay display = new TabbedBookDataDisplay();
75 pnlPassg = new SplitBookDataDisplay(sidebar, display);
76 pnlPassg.showSidebar(showSidebar);
77 sidebar.addKeyChangeListener(pnlSelect);
78 pnlSelect.addCommandListener(sidebar);
79 pnlSelect.addTitleChangedListener(this);
80 pnlPassg.addKeyChangeListener(sidebar);
81 init();
82
83 pnlSelect.doInitialTextDisplay();
85 }
86
87
90 private void init() {
91 try {
92 chooser = new JFileChooser(CWProject.instance().getWriteableProjectSubdir(BOOKMARK_DIR, true).getPath());
93 } catch (IOException ex) {
94 chooser = new JFileChooser(CWProject.instance().getWritableProjectDir().getPath());
95 }
96
97 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
98 chooser.addChoosableFileFilter(new CustomFileFilter());
99 chooser.setMultiSelectionEnabled(false);
100
101 pnlSelect.addCommandListener(new DisplaySelectListener() {
102
105 public void passageSelected(DisplaySelectEvent ev) {
106 pnlPassg.setBookData(ev.getBookProvider().getBooks(), ev.getKey());
107 }
108
109
112 public void bookChosen(DisplaySelectEvent ev) {
113 pnlPassg.setBookData(ev.getBookProvider().getBooks(), ev.getKey());
114 }
115 });
116
117 pnlSelect.setBorder(UIManager.getBorder("SelectPanel.border"));
118
119 this.setLayout(new BorderLayout());
120 this.setMinimumSize(new Dimension(0, 0));
121 this.add(pnlSelect, BorderLayout.NORTH);
122 this.add(pnlPassg, BorderLayout.CENTER);
123 GuiUtil.applyDefaultOrientation(this);
124 }
125
126
129 public void clear() {
130 saved = null;
131 if (!pnlSelect.isClear()) {
132 pnlSelect.clear();
133 }
134 }
135
136
139 public boolean isClear() {
140 saved = null;
141 return pnlSelect.isClear();
142 }
143
144
147 public String getTitle() {
148 if (saved == null) {
149 return pnlSelect.getTitle();
150 }
151
152 return saved.getName();
153 }
154
155
158 public void save() throws IOException {
159 Key key = getKey();
160 if (key == null) {
161 return;
162 }
163
164 if (saved == null && !querySaveFile()) {
166 return;
167 }
168
169 saveKey(key);
170 }
171
172
177 public void saveAs() throws IOException {
178 Key key = getKey();
179 if (key == null) {
180 return;
181 }
182
183 querySaveFile();
184
185 saveKey(key);
186 }
187
188
196 private void saveKey(Key key) throws IOException {
197 assert saved != null;
205
206 Writer out = null;
207 try {
208 out = new FileWriter(saved);
209 if (key instanceof Passage) {
210 Passage ref = (Passage) key;
211 ref.writeDescription(out);
212 } else {
213 out.write(key.getName());
214 out.write("\n");
215 }
216 } finally {
217 if (out != null) {
218 out.close();
219 }
220 }
221 }
222
223
226 public boolean maySave() {
227 return getKey() != null;
228 }
229
230
236 public void open() throws NoSuchVerseException, IOException {
237 int reply = chooser.showOpenDialog(getRootPane());
239 if (reply == JFileChooser.APPROVE_OPTION) {
240 saved = chooser.getSelectedFile();
241 if (saved.length() == 0) {
242 Reporter.informUser(getRootPane(), BDMsg.gettext("File {0} is empty", saved.getName()));
244 return;
245 }
246
247 Reader in = null;
248 try {
249 in = new FileReader(saved);
250 Passage ref = PassageKeyFactory.readPassage(in);
251 setKey(ref);
252 } finally {
253 if (in != null) {
254 in.close();
255 }
256 }
257 }
258 }
259
260
263 private boolean querySaveFile() {
264 if (saved == null) {
265 File guess = new File(getTitle() + EXTENSION);
266 chooser.setSelectedFile(guess);
267 } else {
268 chooser.setSelectedFile(saved);
269 }
270
271 int reply = chooser.showSaveDialog(getRootPane());
272 if (reply == JFileChooser.APPROVE_OPTION) {
273 saved = chooser.getSelectedFile();
274 return true;
275 }
276 return false;
277 }
278
279
282 public Key getKey() {
283 return pnlPassg.getKey();
286 }
287
288
291 public final void setKey(Key key) {
292 pnlSelect.setKey(key);
293 }
294
295
298 public SplitBookDataDisplay getPassagePane() {
299 return pnlPassg;
300 }
301
302
305 public DisplaySelectPane getSelectPane() {
306 return pnlSelect;
307 }
308
309
312 public synchronized void addTitleChangedListener(TitleChangedListener li) {
313 listeners.add(TitleChangedListener.class, li);
314 }
315
316
319 public synchronized void removeTitleChangedListener(TitleChangedListener li) {
320 listeners.remove(TitleChangedListener.class, li);
321 }
322
323
329 protected void fireTitleChanged(TitleChangedEvent ev) {
330 Object[] contents = listeners.getListenerList();
332
333 for (int i = contents.length - 2; i >= 0; i -= 2) {
336 if (contents[i] == TitleChangedListener.class) {
337 ((TitleChangedListener) contents[i + 1]).titleChanged(ev);
338 }
339 }
340 }
341
342
345 public void titleChanged(TitleChangedEvent ev) {
346 if (saved == null) {
347 fireTitleChanged(new TitleChangedEvent(BibleViewPane.this, getTitle()));
348 }
349 }
350
351
358 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
359 listeners = new EventListenerList();
360 is.defaultReadObject();
361 }
362
363 protected File saved;
364 private transient EventListenerList listeners;
365 private DisplaySelectPane pnlSelect;
366 protected SplitBookDataDisplay pnlPassg;
367 private JFileChooser chooser;
368 private static final String BOOKMARK_DIR = "bookmarks";
369 private static final String EXTENSION = ".lst";
370
371
374 protected static final Logger log = Logger.getLogger(BibleViewPane.class);
375
376
379 private static final long serialVersionUID = 3258415036346282038L;
380
381
384 static final class CustomFileFilter extends FileFilter {
385
388 @Override
389 public boolean accept(File file) {
390 return file.getName().endsWith(EXTENSION);
391 }
392
393
396 @Override
397 public String getDescription() {
398 return BDMsg.gettext("Verse Lists ({0})", EXTENSION);
400 }
401 }
402 }
403