/*
* (c) Copyright 2009 Tim Jenkins
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.screenrunner.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.screenrunner.ScreenRunner;
import com.screenrunner.data.Scripture;
import com.screenrunner.data.ScripturePassage;
import com.screenrunner.data.ScriptureVerse;
/**
* @author Tim Jenkins
*
* Scripture picker dialog
* Used for both inserting Scripture passages into the current playlist
* and showing on-the-fly scriptures (in "immediate" mode)
*
*/
public class ScripturePicker extends CookSwingDialog {
public JDialog rootDialog;
public JComboBox versionCombo;
public JList bookList;
public JList chapterList;
public JList startVerseList;
public JList endVerseList;
public JTextArea versePreviewArea;
public JSpinner versesPerSlideSpinner;
public JButton doneButton;
public JButton cancelButton;
public JButton chooseButton;
public JTextField searchField;
private boolean isImmediate = false;
private Scripture curScripture = null;
private int prevVersionIndex = -1;
private int prevBookIndex = -1;
private int prevChapterIndex = -1;
public ScripturePicker(boolean immediate) {
isImmediate = immediate;
}
@Override
protected String getDialogXml() {
return "com/screenrunner/ui/xml/ScripturePicker.xml";
}
@Override
protected void initDialog() {
versionCombo.setModel(new DefaultComboBoxModel(ScreenRunner.scriptures.getBibleNames()));
if(ScreenRunner.scriptures.size() > 0)
versionCombo.setSelectedIndex(0);
versesPerSlideSpinner.setModel(new SpinnerNumberModel(2, 1, 4, 1));
doneButton.setVisible(isImmediate);
cancelButton.setVisible(!isImmediate);
chooseButton.setText((isImmediate ? "Display" : "Add"));
searchField.getDocument().addDocumentListener(search);
}
/**
* General dialog action listener. Handles buttons and
* version combobox changes.
*/
public ActionListener actions = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if(cmd.equals("cancel")) {
setDialogResult(SongPicker.RESULT_CANCEL);
rootDialog.setVisible(false);
}
else if(cmd.equals("ok")) {
if(!isImmediate) {
setDialogResult(SongPicker.RESULT_OK);
rootDialog.setVisible(false);
} else {
showSelectedVerses();
}
}
else if(cmd.equals("versionchange")) {
reloadBooks();
}
else {
System.out.println("FIXME: actions: Unhandled action: '" + cmd + "'");
}
}
};
/**
* Handles selection changes for the 4 main lists on the dialog (book, chapter,
* start verse, end verse)
*/
public ListSelectionListener listSelection = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()) {
if(e.getSource() == bookList) {
reloadChapters();
}
else if(e.getSource() == chapterList) {
reloadVerses();
}
else if(e.getSource() == startVerseList) {
updateEndVerse();
updateVersePreview();
}
else if(e.getSource() == endVerseList) {
updateStartVerse();
updateVersePreview();
}
else {
System.out.println("ScripturePicker: listSelection: unknown source");
}
}
}
};
/**
* Handles changes to the search text field, initiates search on any change
*/
public DocumentListener search = new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
//System.out.println("Searching...");
doSearch();
}
@Override
public void insertUpdate(DocumentEvent e) {
//System.out.println("Searching...");
doSearch();
}
@Override
public void removeUpdate(DocumentEvent e) {
//System.out.println("Searching...");
doSearch();
}
};
/**
* Called when bible version combo box changes. Starts the
* process of refreshing the book/chapter/verse lists.
*/
private void reloadBooks() {
int idx = versionCombo.getSelectedIndex();
if(idx == -1) {
return;
}
if(idx == prevVersionIndex) return;
prevVersionIndex = idx;
int book = bookList.getSelectedIndex();
int chapter = chapterList.getSelectedIndex();
int startVerse = startVerseList.getSelectedIndex();
int endVerse = endVerseList.getSelectedIndex();
prevBookIndex = -1;
prevChapterIndex = -1;
curScripture = ScreenRunner.scriptures.get(idx);
bookList.setListData(curScripture.getBookNames());
bookList.setSelectedIndex((book == -1 ? 0 : book));
chapterList.setSelectedIndex((chapter == -1 ? 0 : chapter));
startVerseList.setSelectedIndex((startVerse == -1 ? 0 : startVerse));
endVerseList.setSelectedIndex((endVerse == -1 ? 0 : endVerse));
}
/**
* Called when the book selection changes. Refreshes the chapter list.
*/
private void reloadChapters() {
int book = bookList.getSelectedIndex();
if(book == -1) { return; }
if(book == prevBookIndex) return;
prevBookIndex = book;
int[] chapters = curScripture.getChapters(book);
String[] chaps = new String[chapters.length];
for(int i = 0; i < chapters.length; i++) {
chaps[i] = Integer.toString(chapters[i]);
}
chapterList.setListData(chaps);
chapterList.setSelectedIndex(0);
}
/**
* Called when the chapter selection changes. Refreshes the verse lists.
*/
private void reloadVerses() {
int book = bookList.getSelectedIndex();
if(book == -1) { return; }
String chapter = (String)chapterList.getSelectedValue();
if(chapter == null) { return; }
int ch = Integer.parseInt(chapter);
if(ch == prevChapterIndex) return;
prevChapterIndex = ch;
int[] verses = curScripture.getVerses(book, ch);
String[] vs = new String[verses.length];
for(int i = 0; i < verses.length; i++) {
vs[i] = Integer.toString(verses[i]);
}
startVerseList.setListData(vs);
endVerseList.setListData(vs);
startVerseList.setSelectedIndex(0);
endVerseList.setSelectedIndex(0);
}
/**
* Called when the startVerse list changes. Ensures that
* the end verse selection is below the start verse selection.
*/
private void updateEndVerse() {
int start = startVerseList.getSelectedIndex();
if(start == -1) return;
int end = endVerseList.getSelectedIndex();
if(end < start) {
endVerseList.setSelectedIndex(start);
endVerseList.ensureIndexIsVisible(start);
}
}
/**
* Called when the endVerse list changes. Ensures that the
* start verse selection is above the end verse selection.
*/
private void updateStartVerse() {
int end = endVerseList.getSelectedIndex();
if(end == -1) return;
int start = startVerseList.getSelectedIndex();
if(start == -1 || start > end) {
startVerseList.setSelectedIndex(end);
startVerseList.ensureIndexIsVisible(end);
}
}
/**
* Called when the verse selections change. Displays the
* selected verses in the preview text area.
*/
private void updateVersePreview() {
String a = (String)startVerseList.getSelectedValue();
String b = (String)endVerseList.getSelectedValue();
String c = (String)chapterList.getSelectedValue();
if(a == null || b == null || c == null) return;
int start = Integer.parseInt(a);
int end = Integer.parseInt(b);
int chapter = Integer.parseInt(c);
int book = bookList.getSelectedIndex();
if(book == -1) return;
String text = "";
ScriptureVerse[] verses = curScripture.getVerseText(book, chapter, start, end);
for(int i = 0; i < verses.length; i++) {
text += (i == 0 ? "" : "\n") + Integer.toString(verses[i].getVerse()) + " " + verses[i].getText();
}
versePreviewArea.setText(text);
versePreviewArea.setCaretPosition(0);
}
/**
* Called when the "display" button is clicked in immediate mode.
* Shows the first n verses on the display/preview screens, where
* n is the value of the versesPerSlide spinner.
*/
private void showSelectedVerses() {
String a = (String)startVerseList.getSelectedValue();
String b = (String)endVerseList.getSelectedValue();
String c = (String)chapterList.getSelectedValue();
if(a == null || b == null || c == null) return;
int perSlide = (Integer)versesPerSlideSpinner.getValue();
int start = Integer.parseInt(a);
int end = Integer.parseInt(b);
int book = bookList.getSelectedIndex();
if(book == -1) return;
String ref = bookList.getSelectedValue().toString() + " " + c + ":" + a + "-" + b;
ScripturePassage p = new ScripturePassage(curScripture, ref, perSlide);
Display.getDisplay().prepareNextBackground(ScreenRunner.currentStyle, p.getStyleType());
Display.getDisplay().prepareNextSlide(p, 1, ScreenRunner.currentStyle);
Display.getDisplay().applyChanges();
if((start + perSlide) <= end) {
startVerseList.setSelectedIndex(startVerseList.getSelectedIndex() + perSlide);
}
}
public ScripturePassage getSelectedPassage() {
int perSlide = (Integer)versesPerSlideSpinner.getValue();
String a = (String)startVerseList.getSelectedValue();
String b = (String)endVerseList.getSelectedValue();
String c = (String)chapterList.getSelectedValue();
String ref = bookList.getSelectedValue().toString() + " " + c + ":" + a + "-" + b;
ScripturePassage p = new ScripturePassage(curScripture, ref, perSlide);
return p;
}
/**
* Called when the search button is clicked. Performs a
* reference lookup, and if there is a match, selects that
* passage. Otherwise, performs a full-text search and
* displays the results in the search results pane.
*/
private void doSearch() {
String search = searchField.getText();
ScriptureVerse[] verses = curScripture.getVerseText(search);
if(verses != null) {
bookList.setSelectedIndex(verses[0].getBook());
ListModel m = chapterList.getModel();
for(int i = 0; i < m.getSize(); i++) {
if(m.getElementAt(i).toString().contentEquals(Integer.toString(verses[0].getChapter()))) {
chapterList.setSelectedIndex(i);
break;
}
}
m = startVerseList.getModel();
for(int i = 0; i < m.getSize(); i++) {
if(m.getElementAt(i).toString().contentEquals(Integer.toString(verses[0].getVerse()))) {
startVerseList.setSelectedIndex(i);
break;
}
}
m = endVerseList.getModel();
for(int i = 0; i < m.getSize(); i++) {
if(m.getElementAt(i).toString().contentEquals(Integer.toString(verses[verses.length - 1].getVerse()))) {
endVerseList.setSelectedIndex(i);
break;
}
}
}
else {
//verses = curScripture.fullTextSearch(search);
}
}
}