diff --git a/build.xml b/build.xml
index 6cb105c..278bf9a 100644
--- a/build.xml
+++ b/build.xml
@@ -36,7 +36,7 @@
+ * This class creates a panel that displays all the relevant diacritic characters used in Asian Studies.
+ * In the context of TibEdit, it's constructor takes a TibFrame which is its parent. When the mouse is clicked
+ * on any diacritic character displayed in DiacriticPanel, it inserts that character at the cursor of the
+ * TibFrame's {@link TextPane}. All characters are, of course, in Unicode. The file that is the list of diacrtics
+ * is dia.dat in the /bin/ directory. It is a flat file list of the hexadecimal codes for the Unicode diacritics.
+ * These are read and converted into characters by DiacriticPanel and they are displayed in the order they are read.
+ * Thus, to reorder, modify, or add diacritics, one needs only to make the appropriate changes to the dia.dat file.
+ *
+ * This inner class is a MouseAdapter that implements "mousePressed". It is added to a label with a diacritic
+ * so that when that label is clicked, the corresponding Unicode diacritic character is inserted in the
+ * open document, a {@link TextPane}, at the cursor.
+ *
+ * This version of mousePressed. Takes the {@link TibFrame} supplied with the DiacriticPanel's constructor
+ * and gets its {@link TextPane}. It then inserts the Unicode diacritic character from the source
+ * label at the cursor of this text pane.
+ *
+ * This version of mousePressed. Takes the {@link TibFrame} supplied with the DiacriticPanel's constructor
+ * and gets its {@link TextPane}. It then inserts the Unicode diacritic character from the source
+ * label at the cursor of this text pane.
+ *
+* This extension of {@link TibAction} is for Edit menu actions.Its constructor takes a String name and a TibFrame parent. With these it calls its
+* super constructor. The action performed takes the following action commands:
+*
+* Element List is a list of elements and ranges. The ranges refer to the {@link TextPanel} locations
+* where the text for that element is found. The {@link #getElement} method takes an integer location
+* in the TextPanel and returns the
+ * IDFactory is a helper class that takes a {@link TibDoc} in its constructor,
+ * processes that doc so that certain information (tags and data) within it is
+ * easily accessible for display and modification. This information has to do with
+ * the identification of the text. ID numbers and so forth.
+ *
+ * This methods is called as the initializing method for this class. It takes
+ * the {@link TibDoc} given in the constructor and processes it finding the relavant
+ * information for its identification. It does this by reading through the TIBID elements
+ * contained in the TIBIDDECL and extracting from their children edition name, sigla, volume
+ * volume letter, text number, pagination.
+ * And from the sources listed in the control info section.
+ *
+*
+*/
+
+public class EditAction extends TibAction
+{
+
+ public EditAction(String name, TibFrame f)
+ {
+ super(name,f);
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String command = e.getActionCommand();
+
+ if(command.equals(TRANS_EDIT))
+ {
+ getController().editTranslation();
+ } else if(command.equals(NORM_EDIT))
+ {
+ org.jdom.Element normTitle = getController().getTibDoc().getTitleFactory().getNormalizedTitle();
+ getController().setSelectedElement(normTitle);
+ getController().enterTranslation();
+ } else if(command.equals(REMOVE_APP))
+ {
+ getController().removeApp();
+ } else if(command.equals(REMOVE_TITLE)) {
+ getController().removeTitle();
+ } else if(command.equals(REMOVE_EDITION)) {
+ getFrame().chooseEdition();
+ }
+ }
+}
diff --git a/source/org/thdl/tib/bibl/ElementList.java b/source/org/thdl/tib/bibl/ElementList.java
new file mode 100644
index 0000000..a499b21
--- /dev/null
+++ b/source/org/thdl/tib/bibl/ElementList.java
@@ -0,0 +1,91 @@
+/*
+The contents of this file are subject to the THDL Open Community License
+Version 1.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License on the THDL web site
+(http://www.thdl.org/).
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific terms governing rights and limitations under the
+License.
+
+The Initial Developer of this software is the Tibetan and Himalayan Digital
+Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL.
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+*/
+
+package org.thdl.tib.bibl;
+
+import java.util.*;
+import org.jdom.*;
+
+/**
+* org.jdom.Element
that is associated with that location
+* if ther is one! If not, it returns null
, indicating there is nothing to edit at
+* that location. This is created by the TextPanel and given to the {@link TiblEdit} controller so
+* it can turn on and off menu options and functionality, depending on the position of the cursor in
+* the TextPane.
+*
+ * This method takes a string as its parameter that is in the usual master ID format with subcategories + * separated by the period or the {@link TibConstants#DOX_DELIM DOX_DELIM}. It parses it through a + * StringTokenizer and using the {@link #masterTibid} fills out the information. It does not however + * set the text's number within the category but it leaves a last Tibid empty ready for that information. + *
+ * + * @param String - the master ID string + * + * @Return String - the new file name based on the master ID + */ + public void setMasterID(String masterID) + { + if(masterID == null) {return;} + StringTokenizer toker = new StringTokenizer(masterID.trim(),DOX_DELIM); + + // The first child is the Ng1, Ng2, Ng3,or Ng4 sigla. + child = masterTibid.getChild(TID); + child.setAttribute(TYPE,ED); + child.setAttribute(SYS,SIG); + + while(child != null && toker.hasMoreTokens()) { + child.setText(toker.nextToken()); + child.setAttribute(TYPE,CLASS); + child.setAttribute(SYS,NUMB); + parent = child; + child = child.getChild(TID); + } + + while(toker.hasMoreTokens()) { + child = new org.jdom.Element(TID); + child.setAttribute(TYPE,CLASS); + child.setAttribute(SYS,NUMB); + child.setText(toker.nextToken()); + parent.addContent(child); + parent = child; + child = null; + } + + if(child == null) { + child = new org.jdom.Element(TID); + parent.addContent(child); + } + + // For the text number use the first three words of the title for now. + child.setAttribute(TYPE,TEXT); + child.setAttribute(SYS,NUMB); + + } + + public org.jdom.Element[] getSourceFiles() + { + org.jdom.Element controlinfo = tibDoc.findElement(CONTROL); + Iterator it = controlinfo.getChildren(RESPSTM).iterator(); + if(it != null) { + while(it.hasNext()) { + org.jdom.Element respStmt = (org.jdom.Element)it.next(); + String nAtt = respStmt.getAttributeValue(N); + if(nAtt != null && nAtt.equals(SRC)) + return tibDoc.toElementArray(respStmt.getChildren(NAME)); + } + } + return null; + } + + public boolean hasEdition(String sigla) + { + if(editions.indexOf(sigla)>-1) { + return true; + } + return false; + } + + public String getEdName(String sigla) + { + return (String)ed_names.get(sigla); + } + + public String getTextNum(String sigla) + { + return (String)textNums.get(sigla); + } + + public String getVolNum(String sigla) + { + return (String)vols.get(sigla); + } + + public String getVolLet(String sigla) + { + return (String)vol_lets.get(sigla); + } + + public String getNumInVol(String sigla) + { + return (String)num_in_vols.get(sigla); + } + + public String getPagination(String sigla) + { + return (String)pages.get(sigla); + } + + public Vector getEditionsConsulted() + { + return editions; + } + + public boolean addEditionConsulted(String[] info) + { + //System.out.println("Text's TibidDecl: \n" + TiblEdit.outputString(tibidDecl)); + if(info.length != NEW_ED_INFO_SPECS.length) { + System.out.println("The information given to add an edition in IDFactory is not the right size: " + info.length); + return false; + } + try{ + sigla = info[1]; + + grandparent = new org.jdom.Element(TID); + grandparent.setAttribute(CORRESP,sigla); + grandparent.setAttribute(TYPE,ED); + grandparent.setAttribute(SYS,LET); + grandparent.setText(info[0]); + + parent = new org.jdom.Element(TID); + parent.setAttribute(TYPE,ED); + parent.setAttribute(SYS,SIG); + parent.setText(sigla); + grandparent.addContent(parent); + + tibid = new org.jdom.Element(TID); + tibid.setAttribute(TYPE,TEXT); + tibid.setAttribute(SYS,NUMB); + tibid.setText(info[2]); + parent.addContent(tibid); + + tibid = new org.jdom.Element(TID); + tibid.setAttribute(TYPE,VOL); + tibid.setAttribute(SYS,NUMB); + tibid.setText(info[3]); + parent.addContent(tibid); + + parent = tibid; + altid = new org.jdom.Element(ALT); + altid.setAttribute(SYS,LET); + altid.setAttribute(LANG,TIB); + altid.setText(info[4]); + parent.addContent(altid); + + tibid = new org.jdom.Element(TID); + tibid.setAttribute(TYPE,TXT); + tibid.setAttribute(SYS,NUMB); + tibid.setText(info[5]); + parent.addContent(tibid); + + tibidDecl.addContent(grandparent); + + num = new org.jdom.Element(NUM); + num.setAttribute(CORRESP,sigla); + num.setText(info[6]); + pagination.addContent(num); + + processDoc(); + + return true; + + } catch (org.jdom.IllegalAddException iae) { + System.out.println("Illegal add exception (JDOM) caught in trying to create new edition tibid in IDFactory!"); + } + addSourceConsulted(sigla,tibDoc.getEditorID(),tibDoc.getEditorName()); + return false; + } + + public void removeEd(String sigla) + { + tibid = findEdTibid(sigla); + if(tibid != null) + { + tibid.detach(); + } + } + + public org.jdom.Element findEdTibid(String sigla) + { + if(ed_tibids == null) {return null;} + for(int n=0;n
+* TTFileView test to see if a file is an .xml file and if so, assumes it's a Tibbibl
+* and searches for the first <title> element and sets the file's description to that.
+* It then uses this description for the name of the text by overriding the {@link #getName} function.
+* This is used in for the {@link javax.swing.JFileChooser} in FileAction
so that
+* when the open-file window appears it lists the text names instead of the file names.
+*
+ * Overrides the ancestor's--{@link javax.swing.JFileChooser.FileView}--getName() function + * so that it returns the text title as the name, if it is an XML file. This has the + * effect of presenting a list of text names in the open dialog rather than their less + * comprehensible file names. + *
+ * + * @param flFile
whose name is requested.
+ * @return String
the description of the file which has been set to
+ * the text title if it is an XML file.
+ *
+ */
+ public String getName(File fl) {
+ if(getDescription(fl) == null && fl.getName().indexOf(".xml")>-1)
+ putDescription(fl);
+ return getDescription(fl);
+ }
+
+ /**
+ *
+ * Adds a description to the file, if the file is an XML file and the docHandler
,
+ * that is an {@link XMLReader}, successfully processes the document and returns a {@link TibDoc}.
+ * Furthermore, it must find a <title> element (the first in the document) with some text.
+ * If all these conditions are met, the description of the file is set to the text of the title
+ * element. Otherwise, the description is set to null
.
+ *
+ * This is the TibDoc
that is the XML document from which the information for
+ * the JTextPane
's document comes. It needs to be here so we can use it functionality
+ * to navigate the XML hierarchy and extract certain information.
+ *
+ * This is a two-dimensional array of {@link org.jdom.Element}s that holds the titles displayed in + * this text pane, with the strings starting position, and length. It is used to reference the + * element for editing when the cursor is positioned on a specific title. + *
+ */ + Object[][] titleRefs; + + int caretPos; + + /** + *+ * This and the following are static, style constants, i.e. names of the styles + *
+ */ + public static String REG = "regular"; + public static String HEAD = "header"; + public static String HEAD_ITALIC = "headitalic"; + public static String TEXT_HEAD = "textheader"; + public static String TEXT_HEAD_ITALIC = "textheaderItalic"; + public static String ITALIC = "italic"; + public static String BOLD = "bold"; + public static String ADD = "addition"; + public static String VARIANT = "variant"; + public static String RED = "red"; + public static String SMALL = "small"; + public static String LARGE = "large"; + + public void setController(TiblEdit tt) + { + controller = tt; + } + + public TiblEdit getController() + { + return controller; + } + + /** + *
+ * This method takes a string array of phrases and a string array of associated style names
+ * iterates through them and inserts the strings with their styles one by one into
+ * this TextPane
's document.
+ *
String[]
- The array of text phrases to be added to the document
+ * @param String[]
- The array of styles associated with the respective text phrases.
+ */
+ public void setTextPane(String[] phrases, String[] styles)
+ {
+ javax.swing.text.StyledDocument doc = new DefaultStyledDocument();
+ setDocument(doc);
+ caretPos = 0;
+ try {
+ for (int i=0; i < phrases.length; i++) {
+ int lng = doc.getLength();
+ doc.insertString(lng, phrases[i],
+ this.getStyle(styles[i]));
+ if(phrases[i].indexOf(ENTER_TRANS_PHRASE)>-1 || phrases[i].indexOf(ENTER_NORM_TRANS_PHRASE)>-1) {
+ caretPos = doc.getLength();
+ }
+ }
+ } catch (BadLocationException ble) {
+ System.err.println("Couldn't insert initial text.");
+ }
+ if(caretPos > -1) {
+ try {
+ setCaretPosition(caretPos);
+ getCaret().setVisible(true);
+ } catch (IllegalArgumentException ia) {System.out.println("Illegal argument in setting caret pos: " + caretPos);}
+ } else {
+ getCaret().setVisible(false);
+ }
+ }
+
+ // Document this: it overrides the above, adding a list of elements that are associated with
+ // the text runs and returns and {@link ElementList} for referencing.
+ public ElementList setTextPane(Vector styleElements)
+ {
+ javax.swing.text.Document doc = this.getDocument();
+ ElementList elemList = new ElementList();
+ caretPos=0;
+ int len = styleElements.size();
+ String phrase = new String();
+ String style = new String();
+ Iterator it = styleElements.iterator();
+ int n = 0;
+ while(it.hasNext())
+ {
+ ElementStyle es = (ElementStyle)it.next();
+ phrase = es.getText();
+ style = es.getStyle();
+
+ try {
+ int lng = doc.getLength();
+ int end = lng + phrase.length();
+ doc.insertString(lng, phrase, this.getStyle(style));
+ elemList.addEntry(lng,end,es);
+ if(phrase.indexOf(ENTER_TRANS_PHRASE)>-1 || phrase.indexOf(ENTER_NORM_TRANS_PHRASE)>-1) {
+ caretPos = doc.getLength();
+ }
+
+ } catch (BadLocationException ble) {
+ System.err.println("Couldn't insert initial text.");
+ }
+ }
+ if(caretPos > -1) {
+ try {
+ setCaretPosition(caretPos);
+ getCaret().setVisible(true);
+ } catch (IllegalArgumentException ia) {System.out.println("Illegal argument in setting caret pos: " + caretPos);}
+ } else {
+ getCaret().setVisible(false);
+ }
+
+ return elemList;
+ }
+
+ /*
+ *+ * This method serves to reset the text + * pane with a blank document with initialized styles ready to open another + * tibbibl. + *
+ */ + public void reset() + { + setDocument(new DefaultStyledDocument()); + initStyles(); + } + + // Helper Methods + /** + *+ * This method initializes the styles used for the given {@link JTextPane}. + * It adds a regular, italic, bold, small, and large styles, plus styles that + * change the background color to green, yellow, or red to indicate different + * types of annotations. Green = addition; yellow = alternative reading or variant; + * red = omission/deletion. + *
+ * + * @paramJTextPane
to which the new styles are added.
+ *
+ */
+ protected void initStyles() {
+
+ Style def = StyleContext.getDefaultStyleContext().
+ getStyle(StyleContext.DEFAULT_STYLE);
+ StyleConstants.setFontFamily(def, BASE_FONT_NAME);
+ StyleConstants.setFontSize(def,BASE_FONT_SIZE);
+
+ Style regular = this.addStyle(REG, def);
+
+ Style header = this.addStyle(HEAD, regular);
+ StyleConstants.setBold(header, true);
+ StyleConstants.setUnderline(header, true);
+ StyleConstants.setFontSize(header,HEAD_FONT_SIZE);
+
+ Style s = this.addStyle(HEAD_ITALIC, header);
+ StyleConstants.setItalic(s, true);
+
+ Style textHeader= this.addStyle(TEXT_HEAD,regular);
+ StyleConstants.setBold(textHeader, true);
+ StyleConstants.setFontSize(textHeader,TEXT_HEAD_SIZE);
+
+ s = this.addStyle(TEXT_HEAD_ITALIC,textHeader);
+ StyleConstants.setItalic(s,true);
+
+ s = this.addStyle(ITALIC, regular);
+ StyleConstants.setItalic(s, true);
+
+ s = this.addStyle(BOLD, regular);
+ StyleConstants.setBold(s, true);
+
+ s = this.addStyle(ADD,regular);
+ StyleConstants.setBackground(s,Color.green);
+
+ s = this.addStyle(VARIANT,regular);
+ StyleConstants.setBackground(s,Color.yellow);
+
+ s = this.addStyle(RED,regular);
+ StyleConstants.setForeground(s,Color.red);
+
+ s = this.addStyle(SMALL, regular);
+ StyleConstants.setFontSize(s, 10);
+
+ s = this.addStyle(LARGE, regular);
+ StyleConstants.setFontSize(s, 16);
+
+ }
+
+ public int getOffset()
+ {
+ return caretPos;
+ }
+
+ public int getPreviousParagraphIndex()
+ {
+ int start = getSelectionStart();
+ if(start>-1) {
+ String fulltxt = getText();
+ int lastP = fulltxt.lastIndexOf("\n",start);
+ return lastP;
+ }
+ return start;
+ }
+
+ public JScrollPane getScrollPane()
+ {
+ JScrollPane jsp = new JScrollPane(this,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ return jsp;
+ }
+
+ // Constructors
+
+ public TextPane(TiblEdit tt)
+ {
+ super();
+ setController(tt);
+ initStyles();
+ addMouseListener(controller);
+ setEditable(false);
+ setCaretPosition(0);
+ caretPos = 0;
+ setMargin(new Insets(10,10,10,10));
+ }
+}
+
diff --git a/source/org/thdl/tib/bibl/TibAction.java b/source/org/thdl/tib/bibl/TibAction.java
new file mode 100644
index 0000000..433175d
--- /dev/null
+++ b/source/org/thdl/tib/bibl/TibAction.java
@@ -0,0 +1,55 @@
+/*
+The contents of this file are subject to the THDL Open Community License
+Version 1.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License on the THDL web site
+(http://www.thdl.org/).
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific terms governing rights and limitations under the
+License.
+
+The Initial Developer of this software is the Tibetan and Himalayan Digital
+Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL.
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+*/
+
+package org.thdl.tib.bibl;
+
+import javax.swing.AbstractAction;
+import java.io.File;
+
+/**
+* This extension of javax.swing.AbstractAction is used for the various menus in {@link TibFrame}. It assigns two
+* special key/value pairs: the frame, which points to the TibFrame, and the controller which is the main program,
+* TiblEdit.
+*/
+
+abstract class TibAction extends AbstractAction implements TibConstants
+{
+ // Accessors
+ public void setKeys(TibFrame f)
+ {
+ putValue(FRAME,f);
+ putValue(CONTROLLER,f.getController());
+ }
+
+ public TibFrame getFrame()
+ {
+ return (TibFrame)getValue(FRAME);
+ }
+
+ public TiblEdit getController()
+ {
+ return (TiblEdit)getValue(CONTROLLER);
+ }
+
+ // Constructor
+ TibAction(String name, TibFrame f)
+ {
+ super(name);
+ setKeys(f);
+ }
+}
diff --git a/source/org/thdl/tib/bibl/TibConstants.java b/source/org/thdl/tib/bibl/TibConstants.java
new file mode 100644
index 0000000..1333791
--- /dev/null
+++ b/source/org/thdl/tib/bibl/TibConstants.java
@@ -0,0 +1,499 @@
+/*
+The contents of this file are subject to the THDL Open Community License
+Version 1.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License on the THDL web site
+(http://www.thdl.org/).
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific terms governing rights and limitations under the
+License.
+
+The Initial Developer of this software is the Tibetan and Himalayan Digital
+Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL.
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+*/
+
+package org.thdl.tib.bibl;
+
+import java.io.*;
+import java.awt.*;
+import javax.swing.*;
+import java.util.Hashtable;
+
+/**
+* This interface contains all the constants used throughout the TiblEdit program. They are roughly organized
+* according to type, but the organization could definitely be cleaned up some.
+*/
+
+public interface TibConstants
+{
+
+ // File Constants
+ final String DEFAULT_DIRECTORY = System.getProperties().getProperty("user.dir");
+ final String BIN = "\\bin\\";
+ final String DATA_DIRECTORY = "\\data\\";
+ final String OUT_DIRECTORY = "\\data\\";
+ final String BIN_LOGIN = "\\bin\\logs\\";
+ final String DIA_DATA = "\\bin\\dia.dat";
+ final String TEMP_DIR = "\\bin\\temp\\";
+ final String PREFS = "ttprefs.ini";
+
+ final String PREFS_DELIM = "=";
+
+ // Frame Constants
+ final String PROG_NAME = "TiblEdit: ";
+ final String DEFAULT_HEADER = PROG_NAME + "An XML Editor for Tibetan Bibliographic Records";
+
+ // Menu Constants
+ // File Menu
+ final String FILE = "File";
+ final String OPENFILE = "Open";
+ final String TITLEOPENFILE = "Open by Title";
+ final String CLOSEFILE = "Close";
+ final String SAVE = "Save";
+ final String SAVEAS = "Save As";
+ final String EXPORT = "Export";
+ final String EXIT = "Exit";
+
+ // Edit Menu
+ final String EDIT = "Edit";
+ final String TRANS_EDIT = "Translation";
+ final String NORM_EDIT = "Normalized Title";
+ final String REMOVE_APP = "Remove Variants";
+ final String REMOVE_TITLE = "Remove Title";
+ final String REMOVE_EDITION = "Remove Edition";
+
+ // Insert Menu
+ final String INSERT = "Insert";
+ final String ED_INFO = "New Edition Info";
+ final String CRIT_TITLE = "Critical Title";
+ final String ED_TITLE = "Edition Title";
+ final String TITLE_DISC = "Insert Discussion";
+ final String INSERT_APP = "Variant Reading";
+
+ // View Menu
+ final String VIEW = "View";
+ final String TITLES_VIEW = "View Titles";
+ final String MASTER_ID_VIEW = "Master ID/Doxography";
+ final String USER_ID_VIEW = "Editor's Info";
+
+ final String EDCON = "Editions Consulted";
+ final String DIAC = "Diacritics";
+ final String ABOUT = "About TiblEdit";
+
+ // TibAction Constants (should these go in TibAction?
+ final String CONTROLLER = "controller";
+ final String FRAME = "frame";
+ final String CURR_DIR = "current directory";
+
+ final String[] NGDIVS = { "Atiyoga", "Anuyoga", "Mah\u0101yoga", "Unclassified" };
+ final String[] NGSIGS = { "Ng1", "Ng2", "Ng3", "Ng4" };
+ final String OTHER = "Other Edition";
+ final String EDS_CORR = "Editor's Correction";
+ final String[] OTHER_EDS = { "Tk","Dg","Kg","Wa","Bg",OTHER};
+ final int SELDIV = 0;
+ final String GEN = "General";
+
+
+ // Button labels
+ final String SUBMIT = "Submit Translations";
+ final String ENTER = "Enter";
+ final String CANCEL = "Cancel";
+ final String ADD_DOX = "Add Doxographical Sub-category";
+
+ // Labels & Headers
+ final String LABEL_SPACE = " ";
+ final String CROSSREF = "Cross-references:";
+ final String NORM_TITLE_HEAD = "Normalized Title\n";
+ final String NORM_TIB_LABEL = "Normalized Title (Tib): ";
+ final String NORM_ENG_LABEL = "Normalized Title (Eng): ";
+ final String TITLE_LINE_HEAD = "\nTitle Line\n";
+ final String EOC_TITLES_HEAD = "\nEnd of Chapter Titles\n";
+ final String NON_TIB_TITLE_HEAD = "\nNon-Tibetan Title\n";
+ final String CHAP_TITLES_HEAD = "\nChapter Titles\n";
+ final String CLOSE_TITLE_HEAD = "Back Titles";
+ final String NON_TIB_HEAD = "\nNon-Tibetan Title\n";
+ final String SRCS_LABEL = "Sources: ";
+ final String ENTER_PLACE = " \n";
+ final String ENTER_TRANS_PHRASE = "\nEnter Translation: ";
+ final String ENTER_TITLE_PHRASE = "\nEnter Title: ";
+ final String ENTER_NORMALIZED_PHRASE= "Normalized title: ";
+ final String ENTER_NORM_TRANS_PHRASE= "Translation: ";
+ final String DOX_WINDOW_TITLE = "Doxographic Classification/Master ID Number";
+ final String DISC_DIA_TITLE = "Discussion Entry Form";
+ final String SEPARATOR = "------------------------------------\n";
+
+ // Fonts
+ final String BASE_FONT_NAME = "Arial Unicode MS";
+ int BASE_FONT_SIZE = 14;
+ int HEAD_FONT_SIZE = 16;
+ int TEXT_HEAD_SIZE = 18;
+ final Font DEFAULT_FONT = new Font(BASE_FONT_NAME,Font.PLAIN,BASE_FONT_SIZE);
+ final Font TITLE_FONT = new Font(BASE_FONT_NAME,Font.ITALIC,BASE_FONT_SIZE);
+ final Font MENU_FONT = new Font(BASE_FONT_NAME,Font.PLAIN,12);
+ final Font BOLD_FONT = new Font(BASE_FONT_NAME,Font.BOLD,BASE_FONT_SIZE);
+ final Font HEAD_FONT = new Font(BASE_FONT_NAME,Font.BOLD,HEAD_FONT_SIZE);
+
+ // Styles (names)
+ final String BOLD = "bold";
+ final String ITALIC = "italics";
+
+ // Sizes
+ final Dimension TIBPANEL_SIZE = new Dimension(10,10);
+ final Dimension BUTTON_SIZE = new Dimension(100,30);
+ final Dimension SHORT_LABEL_SIZE = new Dimension(100,75);
+ final Dimension LABEL_SIZE = new Dimension(500,75);
+ final Dimension ED_SCROLL_SIZE = new Dimension(400,400);
+ final Dimension BUTT_PANEL_SIZE = new Dimension(500,500);
+ final Dimension DEFAULT_PANEL_SIZE = new Dimension(550,600);
+
+ final int TTFCOLS = 30;
+ final int TEXT_FIELD_SIZE = 15;
+
+ // Colors
+ final Color DEFAULT_BGCOLOR = new Color(250,250,250);// 250,235,215); // antique white
+ final Color DEFAULT_BUTTON_COLOR = new Color(200,180,200);
+ final Color LIST_COLOR = Color.blue;
+ final Color TEXT_COLOR = Color.black;
+
+ // Insets & Borders
+ final Insets DEFAULT_INSETS = new Insets(10,0,10,10);
+ final Insets LIST_INSETS = new Insets(10,10,10,1000);
+ final Insets MAIN_MARGINS = new Insets(10,10,10,10);
+ final Insets BUT_MARGINS = new Insets(25,25,25,25);
+
+ // Integer Constants (choices)
+ final int NORM = 1; // Normalized title choice & normal display mode choice
+ final int TITLELINE = 2; // Title line choice
+ final int EOC = 3; // End of chapter titles choice.
+ final int CLOSING = 4; // Closing section titles.
+ final int NONTIBET = 5; // Non-Tibetan title choice.
+ final int CHAPS = 6; // Chapter titles.
+
+ // Display Modes
+ final int ENTER_TRANS = 2; // for entering a translation
+ final int NEW_TITLE = 3; // for entering a new title
+ final int NEW_AP = 4; // for entering a new app
+ final int CANCEL_NEW_APP = 5; // When a new app entry is cancelled.
+ final int SHOW_AP = 6; // when showing an old app
+ final int ENTER_NORMALIZED = 7; // when entering a normalized title.
+ final int CANC = 8; // for cancelling
+ final int DO_TRANS = 9; // for editing a translation
+
+ final String YES = "yes";
+ final String NO = "no";
+ final String IS_FILE_LIST = "filelist";
+ final String AP_CHECK = "Checking app!";
+ final String ED_TITLE_REM = "Removing Edition Title";
+ // Observer types and hashkeys
+ final String TABLE = "table";
+ final String APP_SUBMIT = "Submit App";
+ final String REDISPLAY = "Redisplay";
+ // also uses AP for app and TYPE for type keys.
+ final String RECENT = "recent_file";
+ final int RECENT_FILE_SIZE = 8;
+ // XML Constants
+ // sigla constants
+ final String NG = "Ng";
+ final String TB = "Tb";
+ final String TK = "Tk";
+ final String DG = "Dg";
+ final String BG = "Bg";
+ final String KG = "Kg";
+
+ final String[] EDNAMES = {"Master","mTshams brag","gTing skyes","sDe dge","Bai ro'i rgyud 'bum","sKyid grong"};
+
+ // Element and Attribute Constants
+ final String TIBL = "tibbibl"; // Element/root name
+ final String ID = "id"; // Attribute name
+ final String LVL = "level"; // Attribute name on Tibbibls (either, volume, text, chapter)
+ final String ED = "edition"; // Attribute value
+ final String SIG = "sigla"; // Attribute value
+ final String CLASS = "class"; // Attribute value
+ final String LET = "letter"; // Attribute value
+ final String TXT = "text"; // Attribute value
+ final String CHAPTER = "Chapter"; // Attribute value
+ final String DIV = "div1"; // Element name part
+ final String TYPE = "type"; // Attribute name
+ final String SUBTYPE = "subtype"; // Attribute name
+ final String TEXT = "text"; // Attribute value for DIVs 3 or 4.
+ final String TIBBIBL = "tibbibl"; // Element name for text's root element.
+ final String TITLE = "title"; // Element name
+ final String NORM_TITLE = "Normalized title"; // Attribute value (TYPE)
+ final String FOREIGN = "foreign"; // Element name
+ final String LANG = "lang"; // Attribute name
+ final String TIB = "tib"; // Attribute value
+ final String ENG = "eng"; // Attribute value
+ final String N = "n"; // Attribute name
+ final String P = "p"; // Element name
+ final String TITLEGRP = "titlegrp"; // Element that holds all the titles
+ final String TDECL = "titledecl"; // Element name
+ final String TLIST = "titlelist"; // Element name
+ final String HEAD = "head"; // Element name
+ final String CONTROL = "controlinfo";// ELement name
+ final String SID = "sysid"; // Element name
+ final String RESPDECL = "respdecl"; // Element name
+ final String RESPSTM = "respStmt"; // Element name
+ final String RESP = "resp"; // Element name
+ final String PERSNAME = "persname"; // Element name
+ final String NAME = "name"; // Element name
+ final String DATE = "date"; // Element name
+ final String REVDESC = "revisiondesc";// Element name
+ final String TRANS = "Translator"; // Element content
+ final String TRANS_JOB = "Translated and Edited titles."; // Element content
+ final String CHANGE = "change"; // Element name
+ final String LIST = "list"; // Element name
+ final String ITEM = "item"; // Element name
+ final String TIDDECL = "tibiddecl"; // Element name
+ final String TID = "tibid"; // Element name
+ final String ALT = "altid"; // Element name
+ final String PHYSDEC = "physdecl"; // Element name
+ final String PAGIN = "pagination"; // Element name
+ final String AP = "app"; // Element name
+ final String LM = "lem"; // Element name
+ final String EXPAN = "expan"; // Element name
+ final String ABBR = "abbr"; // Element name
+ final String INTDECL = "intelldecl"; // Element name
+ final String DOX = "doxography"; // Element name
+ final String DOXTYPE = "Doxography"; // Attribute value for doxogrpahy name elements
+ final String CATEG = "category"; // Attribute value for Type of Doxography
+ final String RELAT = "relation"; // Attribute value for Type of Doxography
+ final String SRC = "source"; // Element name
+ final String SYS = "system"; // Attribute name
+ final String NUMB = "number"; // Attribute value on TIBID
+ final String TXTHEAD = "text header";// Attribute value for TITLE type
+ final String TITLELN = "title line"; // Attribute value for Title subtype
+ final String WIT = "wit"; // Attribute name
+ final String RDG = "rdg"; // Element name
+ final String TINFO = "titleinfo"; // Element name
+ final String TDIV = "titlediv"; // Element name
+ final String TITEM = "titleitem";
+ final String DESIG = "designation";
+ final String CORRESP = "corresp"; // Attribute name
+ final String FRONT = "front";
+ final String BODY = "body";
+ final String BACK = "back";
+ final String NONTIB = "nontibet";
+ final String ORIG_LANG = "Original language"; // Attribute value
+ final String TEXT_HEAD = "text header";// Attribute value for type of title
+ final String RS = "rs"; // Element name
+ final String DISC = "discussion"; // Element name
+ final String SUMMARY = "summary"; // Disc Element Type attribute
+ final String SECTIONS = "sections"; // Element name
+ final String TIBANAL = "tibanal"; // Element name
+ final String NUM = "num"; // Element name
+ final String VOL = "volume"; // Attribute value;
+ final String NOTE = "note"; // Element name
+ final String HI = "hi"; // Element name
+ final String CIT = "cit"; // Element name (changed to QUOTE)
+ final String QUOTE = "quote"; // Element name
+ final String REND = "rend"; // Attribute name;
+ final String INFO = "info"; // Attribute (rend) value;
+ final String CREATOR = "creator"; // attribute value in control info
+ final String CONTROL_SOURCE = "source"; // attribute value in control info
+ final String CRIT_ED_LABEL = "crited"; // Attribute value in control info
+ final String CRIT_ED_DESC = "Critical Editing"; // element text phrase for control info
+
+ final String EDCONS = "Editions consulted"; // Rend value of Source for editions consulted.
+ final String MASTER_SIGLA = "Ng"; // Sigla for the Master edition
+ final String ATIYOGA = "a ti yo ga ";// Tibetan spelling
+ final String ANUYOGA = "a nu yo ga ";
+ final String MAHAYOGA = "ma h\u0101 yo ga ";
+ final String MISC = "Miscellaneous";
+ final String UNCLASSED = "Unclassified";
+ final String NOTFOUND = "not found"; // Attribute value for type on RDG elements
+ // The following three use partial strings that are unique but allow to do indexOf to ignore capitalization and punctuation.
+ final String NOT_SPEC = "specified"; // Contents of a title element when title missing.
+ final String NO_TITLE = "title given"; // Contents of a title element when none is given.1z
+ final String UNTITLED = "ntitled"; // Contents of untitled chapter. U not included to match all cases (Don't know why I didn't use equalsIgnoreCase()? Check it out!)
+ final String BRIEF = "Brief"; // Type attribute value for discussion, brief means no paragraphs.
+ final String FULL = "Full"; // Type attribute value for discussion, full means with paragraphs (changed value to long, more descriptive).
+ final String SIGLA_DELIM = " "; // delimits between sigla in a wit attribute
+ final String DATE_DELIM = "-";
+ final String DOX_DELIM = "."; // delimits between dox numbers in ID
+ final String DOX_CAT_DELIM = ":"; // delimits between names of dox categories.
+ final org.jdom.Element NO_ELEM = new org.jdom.Element("null");
+ // To take up a place in vector when there is no element associated with a string/style run in TextPanel
+
+ // Constants for Edition Attributes
+
+ final String ED_NAME = "EDITION_LETTER";
+ final String ED_SIGLA = "EDITION_SIGLA";
+ final String VOL_NUM = "VOLUME_NUMBER";
+ final String VOL_LET = "TIB_LETTER";
+ final String TEXT_NUM = "TEXT_NUMBER";
+ final String VOL_TEXT = "VOL_TEXT_NUMBER";
+ final String PAGE_RANGE = "PAGINATION";
+
+ final org.jdom.Attribute TYPE_ED = new org.jdom.Attribute(TYPE,ED);
+ final org.jdom.Attribute TYPE_VOL = new org.jdom.Attribute(TYPE,VOL);
+ final org.jdom.Attribute TYPE_TEXT = new org.jdom.Attribute(TYPE,TXT);
+ final org.jdom.Attribute TYPE_CLASS = new org.jdom.Attribute(TYPE,CLASS);
+ final org.jdom.Attribute SYS_LET = new org.jdom.Attribute(SYS,LET);
+ final org.jdom.Attribute SYS_SIG = new org.jdom.Attribute(SYS,SIG);
+ final org.jdom.Attribute SYS_NUM = new org.jdom.Attribute(SYS,NUM);
+ final org.jdom.Attribute LANG_TIB = new org.jdom.Attribute(LANG,TIB);
+ final org.jdom.Attribute LANG_ENG = new org.jdom.Attribute(LANG,ENG);
+ final org.jdom.Attribute CORRESP_NG = new org.jdom.Attribute(CORRESP,NG);
+
+ final org.jdom.Attribute TYPE_DOX = new org.jdom.Attribute(TYPE,DOX);
+
+ // Char Constants
+ final char BAD_PARA = ((char)(10)); // Para mark in data file is not understood.
+ final char SPACE = ' '; // A space to replace it with.
+
+ // Messages
+ final String TTITLE_TITLE = "Java Title Translation Program";
+ final String RUNTIME_ERROR = "A runtime error has occurred in ";
+ final String EDITOR_NAME_MESSAGE = "Please your initials for identification.";
+ final String EDITOR_NAME_TITLE = "Editor Identification";
+ final String DATE_MESSAGE = "Is today's date: ";
+ final String DATE_TITLE = "Confirm Date";
+ final String INPUT_DATE_MESSAGE = "Please enter the date (YYYY-MM-DD):";
+ final String INPUT_DATE_TITLE = "Enter Today's Date";
+ final String OPEN_TITLE = "Open XML Tibbibl Record";
+ final String TEXT_LIST_HEAD = "List of Texts in Tb Volume ";
+ final String EX1 = "\"1"+DOX_DELIM + "3" +DOX_DELIM+"6\"";
+ final String EX2 = "\"sems sde " + DOX_CAT_DELIM + " sna tshogs\"";
+
+ // JOptionPane Messages
+ final String JOP_ERROR = Integer.toString(JOptionPane.ERROR_MESSAGE);
+ final String JOP_INFO = Integer.toString(JOptionPane.INFORMATION_MESSAGE);
+ final String JOP_WARN = Integer.toString(JOptionPane.WARNING_MESSAGE);
+ final String JOP_QUEST = Integer.toString(JOptionPane.QUESTION_MESSAGE);
+ final String JOP_YESNOCANCEL = Integer.toString(JOptionPane.YES_NO_CANCEL_OPTION);
+
+ final String[] OPEN_ERROR = {"Could not open the XML file:\n",
+ "Unable to open file!",
+ JOP_ERROR};
+ final String[] DO_ALL_TITLES = {"Add this translation for all identical titles " +
+ "in this text?",
+ "Use Translation for Identical Titles?",
+ JOP_QUEST};
+ final String[] ED_EXISTS_MESSAGE = {"The sigla you have entered has " +
+ "already been added to the list of sources.",
+ "Duplicate Sigla Error",
+ JOP_ERROR};
+
+ final String NEW_ED_INFO = "New Edition Information";
+ final String ED_STRING = "Edition's name";
+ final String ED_SIG = "Edition Sigla";
+ final String ED_TEXT_NUM = "Edition Text Number";
+ final String ED_VOL_NUM = "Edition Volume Number";
+ final String ED_VOL_LET = "Edition Volume Letter";
+ final String VOL_TEXT_NUM = "Text Number in Volume";
+ final String FULL_TEXT_PAGE = "Full Pagination of Text";
+ final String TITLE_PAGE = "New Title's Pagination";
+ final String[] NEW_ED_INFO_SPECS = {ED_STRING,ED_SIG,ED_TEXT_NUM,ED_VOL_NUM, ED_VOL_LET,
+ VOL_TEXT_NUM, FULL_TEXT_PAGE, TITLE_PAGE};
+
+ final String NEW_ED_TITLE_INFO = "New Edition Title Information";
+ final String[] NEW_ED_TITLE_INFO_SPECS = {ED_SIG,TITLE_PAGE};
+ final String GET_DESIG = "Chapter Designation of Title Source";
+ final String GET_DESIG_QUESTION = "Enter the chapter number for the source of this title: ";
+ final String[] GET_DESIG_SPECS = {GET_DESIG_QUESTION,GET_DESIG,JOP_QUEST};
+
+ final String TLIST_WARN_TITLE = "Insertion Not Allowed!";
+ final String TLIST_WARN = "An edition title cannot be inserted into a list of End-of-Chapter titles." +
+ "\nUse Insert Title List under the insertion menu instead.";
+ final String[] TLIST_WARNING = {TLIST_WARN,TLIST_WARN_TITLE,JOP_WARN};
+
+ final String EDITORS_INFO = "Editor's Information";
+ final String EDITORS_NAME = "Your name";
+ final String EDITORS_INITIALS = "Your full initials";
+ final String[] EDITORS_INFO_SPECS = {EDITORS_NAME,EDITORS_INITIALS};
+
+ final String NOT_SPEC_TITLE = "Not Specified Title";
+ final String NOT_SPEC_MESSAGE = "The title you have chosen as the base for a critical title\n" +
+ "is \"Not specified.\" If you wish to enter a title from another source, \n"+
+ "use 'Insert Edition Title' from the Insert Menu. Then, use that as the \n" +
+ "basis of a critical title and translation.";
+ final String[] NOT_SPEC_SPECS = {NOT_SPEC_MESSAGE,NOT_SPEC_TITLE,JOP_ERROR};
+
+ final String NO_TITLE_TITLE = "No Title Given";
+ final String NO_TITLE_MESSAGE = "The title you have chosen as the base for a critical title\n" +
+ "informs us there was \"No title given.\" If you wish to enter a title from another source, \n"+
+ "use 'Insert Edition Title' from the Insert Menu. Then, use that as the \n" +
+ "basis of a critical title and translation.";
+ final String[] NO_TITLE_SPECS = {NO_TITLE_MESSAGE,NO_TITLE_TITLE,JOP_ERROR};
+
+ final String NOT_SAVED_TITLE = "Not Saved!";
+ final String NOT_SAVED_MESSAGE = "Do wish to save changes you have made to this file?";
+ final String[] SAVE_SPECS = {NOT_SAVED_MESSAGE,NOT_SAVED_TITLE,JOP_YESNOCANCEL};
+
+ final String INV_TRANS_TITLE = "Cannot Edit Translation";
+ final String INV_TRANS = "The cursor is not placed in a valid title or translation for editing.\n" +
+ "The cursor must be positioned in a master version of a title (Ng) or in\n" +
+ "its translation for the Edit Translation option.";
+ final String[] INVALID_TRANS_SPECS = {INV_TRANS,INV_TRANS_TITLE,JOP_ERROR};
+
+ final String RENAME_FILE_TITLE = "Tibbibl File Renamed!";
+ final String RENAME_FILE = "The Tibbibl file has been renamed to match the change in its Master ID. \n" +
+ "The new file name is: ";
+ final String[] RENAMING_FILE_SPECS = {RENAME_FILE,RENAME_FILE_TITLE,JOP_INFO};
+
+ final String SAVED_FILE_TITLE = "Tibbibl File Saved!";
+ final String SAVED_FILE = "The Tibbibl file has been saved under a name that matches its Master ID. \n" +
+ "The file name is: ";
+ final String[] SAVED_FILE_SPECS = {SAVED_FILE,SAVED_FILE_TITLE,JOP_INFO};
+
+ final String FILE_EXISTS_TITLE = "File Already Exists!";
+ final String FILE_EXISTS = "The file name generated for this text already exists.\n" +
+ "Do you wish to replace the existing file?\n" +
+ "(If you choose, 'no' another name will be automatically generated for this text.)\n"+
+ "File name: ";
+ final String[] FILE_EXISTS_SPECS = {FILE_EXISTS,FILE_EXISTS_TITLE,JOP_YESNOCANCEL};
+
+ final String ED_EXISTS_TITLE = "Rewrite Edition Info?";
+ final String ED_EXISTS = "The edition you entered is already found in this texts identification information.\n" +
+ "Do you wish to replace this information?";
+ final String[] ED_EXISTS_SPECS = {ED_EXISTS,ED_EXISTS_TITLE,JOP_YESNOCANCEL};
+
+ final String REMOVE_APP_TITLE = "Remove Variants at Cursor?";
+ final String REMOVE_APP_MESS = "Do you want to remove the variant readings at the cursor position?\n" +
+ "They will be replaced by the main reading now showing.";
+ final String[] REMOVE_APP_SPECS = {REMOVE_APP_MESS,REMOVE_APP_TITLE,JOP_YESNOCANCEL};
+
+ final String NO_SELECT_TITLE = "No Text Selected for Variant Readings";
+ final String NO_SELECTION = "You have not selected any text. You must select a range of text \n"+
+ "to which the variant readings will apply.";
+ final String[] NO_SELECTION_SPECS = {NO_SELECTION,NO_SELECT_TITLE,JOP_ERROR};
+
+ final String CREATE_FILE_LIST_TITLE = "No File List!";
+ final String CREATE_FILE_LIST = "No file list has been created.\nWould you like to build the file list?\n" +
+ "This may take some time...";
+ final String[] CREATE_FILE_LIST_SPECS = {CREATE_FILE_LIST,CREATE_FILE_LIST_TITLE,JOP_YESNOCANCEL};
+
+ final String REMOVE_ED_TITLE_TITLE = "Remove Added Title?";
+ final String REMOVE_ED_TITLE_MESS = "Do you wish to remove this title which you have added?";
+ final String[] REMOVE_ED_TITLE_SPECS = {REMOVE_ED_TITLE_MESS,REMOVE_ED_TITLE_TITLE,JOP_YESNOCANCEL};
+
+ final String REMOVE_ED_ERROR_TITLE = "Cannot Remove Title!";
+ final String REMOVE_ED_ERROR_MESS = "The title selected was not entered by you and so cannot be removed by you.";
+ final String[] REMOVE_ED_TITLE_ERROR = {REMOVE_ED_ERROR_MESS,REMOVE_ED_ERROR_TITLE,JOP_INFO};
+
+ final String DEL_EDS_TITLE = "Delete Inserted Edition!";
+ final String DEL_EDS_MESS = "In the table below, double click on the row\nfor the edition you wish to remove.\n" +
+ "(You can only remove editions that you have added.)";
+
+ final String TLIST_ADD_TITLE = "Cannot Add Edition Title";
+ final String TLIST_ADD_MESS = "A new edition title cannot be added to end of chapter titles.\n" +
+ "You can still create a master version of this title and provide alternate readings\n" +
+ "By double clicking on the existing title and using the \"Insert Variant Reading\" option.";
+ final String[] TLIST_ADD_ERROR = {TLIST_ADD_MESS,TLIST_ADD_TITLE,JOP_ERROR};
+
+ final String NORM_AP_TITLE = "Cannot Add Reading to Normalized Title";
+ final String NORM_AP_MESS = "You cannot add a reading to the normalized title.\n" +
+ "The normalized title is an assigned normative title not necessarily\n" +
+ "Found in the text itself. Thus, variant readings cannot be added to it.";
+ final String[] NORM_AP_ERROR = {NORM_AP_MESS,NORM_AP_TITLE,JOP_ERROR};
+
+ final String ED_ID_TITLE = "Editor's Identification Information Required!";
+ final String ED_ID_MESS = "This program cannot function properly unless the user properly identifies him or herself.\n" +
+ "Please enter your full name and your 2 or 3-letter editor initials/ID in the following window.\n" +
+ "(To quit the program without entering your information, press cancel in the next window.)";
+ final String[] ED_ID_REQUIRED = {ED_ID_MESS,ED_ID_TITLE,JOP_ERROR};
+}
diff --git a/source/org/thdl/tib/bibl/TibDTDResolver.java b/source/org/thdl/tib/bibl/TibDTDResolver.java
new file mode 100644
index 0000000..5ebbec9
--- /dev/null
+++ b/source/org/thdl/tib/bibl/TibDTDResolver.java
@@ -0,0 +1,40 @@
+/*
+The contents of this file are subject to the THDL Open Community License
+Version 1.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License on the THDL web site
+(http://www.thdl.org/).
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific terms governing rights and limitations under the
+License.
+
+The Initial Developer of this software is the Tibetan and Himalayan Digital
+Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL.
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+*/
+
+package org.thdl.tib.bibl;
+
+ import org.xml.sax.EntityResolver;
+ import org.xml.sax.InputSource;
+
+ public class TibDTDResolver implements EntityResolver, TibConstants {
+ public InputSource resolveEntity (String publicId, String systemId)
+ {
+ if (systemId.indexOf("dtd")>-1) {
+ // return a special input source
+
+ int lastSlash = systemId.lastIndexOf("/");
+ String fname = "file:/" + DEFAULT_DIRECTORY + BIN + systemId.substring(lastSlash+1);
+ fname = fname.replace('\\','/');
+ InputSource inSrc = new InputSource(fname);
+ return inSrc;
+ } else {
+ // use the default behaviour
+ return null;
+ }
+ }
+ }
diff --git a/source/org/thdl/tib/bibl/TibDialog.java b/source/org/thdl/tib/bibl/TibDialog.java
new file mode 100644
index 0000000..bf82ca9
--- /dev/null
+++ b/source/org/thdl/tib/bibl/TibDialog.java
@@ -0,0 +1,205 @@
+/*
+The contents of this file are subject to the THDL Open Community License
+Version 1.0 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License on the THDL web site
+(http://www.thdl.org/).
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific terms governing rights and limitations under the
+License.
+
+The Initial Developer of this software is the Tibetan and Himalayan Digital
+Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL.
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+*/
+
+package org.thdl.tib.bibl;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+
+/**
+* +* This class is a generic class for displaying a dialog in TiblEdit. I'm not sure if it is actually used in +* TiblEdit. It may be a relic. CHECK! +*
+* +*/ + +public class TibDialog extends JDialog implements ActionListener, TibConstants +{ + // Attributes + TiblEdit controller; + TibFrame frame; + String[] specs; + String response; + int num; + Hashtable results; + JLabel[] jl; + JTextField[] jtf; + String type; + boolean isStartUp = false; + + transient protected String value; + public static final String RESPONSE_PROPERTY = "response"; + public static final String NEW_ED = "new edition"; + + private void init() + { + GridLayout gl = new GridLayout(0,2); + gl.setHgap(5); + gl.setVgap(5); + JPanel cpane = new JPanel(gl); + jl = new JLabel[num]; + jtf = new JTextField[num]; + for(int n=0; n+ * Generic variables for headers, parents, elements/self, and children. + *
+ */ + private org.jdom.Element head, parent, element, child; + + /** + *+ * The {@link TitleFactory} associated with this Tibbibl XML document. + *
+ */ + private TitleFactory tf; + /** + *+ * The {@link IDFactory} associated with this Tibbibl XML document + *
+ */ + private IDFactory idf; + + + // Accessory + /** + *+ * This method sets the first head element or the text header by searching for the first head element. + *
+ */ + protected void setHead() + { + head = findElement(HEAD); + } + + /** + *+ * This returns the text's main head element that contains the text header. + *
+ * + * @return org.jdom.Element - the head element that contains the text's header. + */ + public org.jdom.Element getHead() + { + return head; + } + + /** + *+ * This method sets the {@link #idf IDFactory variable} and the {@link #tf TitleFactory variable} + * for this Tibbibl XML document. + *
+ */ + public void setFactories() + { + tf = new TitleFactory(this); + idf = new IDFactory(this); + } + + /** + *+ * Returns the {@link TitleFactory} created for this document that allows easy access to and + * manipulation of titles. + *
+ * + * @return TitleFactory - The title factory for this Tibbibl XML document. + */ + public TitleFactory getTitleFactory() + { + return tf; + } + + /** + *+ * Returns the {@link IDFactory} created for this document that allows easy access to and + * manipulation of ID information, that is the Tibids contained within the text's TibidDecl. + *
+ * + * @return IDFactory - The ID factory for this Tibbibl XML document. + */ + public IDFactory getIDFactory() + { + return idf; + } + + // Helper methods + + /** + *+ * This method sets the information for the current user (=editor) of the program who is + * entering in translations and adding critical titles to the text. This information is added + * in the ControlInfo metadata section of the Tibbibl document. A Resp/Name pair is added with the + * Name element containing the full name and having an ID of the initials, and a Name element is + * added to the Source list, that has an ID of "Ng" and whose corresp attribute is set to the initials. + * Thus, all uses of the corresp="Ng" are linked to the tag under the list of sources with corresp = to + * the editor's initials and content of the full name. This in turn is linked to the Resp that contains + * the editor's full name and his/her responsibility regarding the document. + *
+ * + * @param String - the editor's (preferrably) three initials, such as snw or dfg. + * @param String - the editor's full name to be recorded in the metadata. + * @param String - the present date. + */ + public void addEditor(String initials, String fullName, String today) + { + initials = initials.trim(); + fullName = fullName.trim(); + setEditorInfo(initials,fullName); + org.jdom.Element parent = findElement(CONTROL); + java.util.List children = parent.getChildren(RESPSTM); + Iterator it = children.iterator(); + int listIndex = -1; + org.jdom.Element respstm, contrlSrc; + contrlSrc = null; + boolean found = false; + + while(it.hasNext()) { + // find the RespStmts in the control info section + respstm = (org.jdom.Element)it.next(); + String nValue = respstm.getAttributeValue(N); + if(nValue == null) {continue;} + if(nValue.equals(CONTROL_SOURCE)) { + // if need to modify the sources + contrlSrc = respstm; + } else if(nValue.equals(CRIT_ED_LABEL)) { + // of if it's already there + found = true; + } + } + + if(!found) { + org.jdom.Element resp, name, date; + respstm = new org.jdom.Element(RESPSTM); + respstm.setAttribute(N,CRIT_ED_LABEL); + resp = new org.jdom.Element(RESP); + resp.setText(CRIT_ED_DESC); + respstm.addContent(resp); + name = new org.jdom.Element(NAME); + name.setText(fullName); + name.setAttribute(ID,initials); + resp.addContent(name); + date = new org.jdom.Element(DATE); + date.setText(today); + resp.addContent(date); + parent.addContent(respstm); + + name = new org.jdom.Element(NAME); + name.setAttribute(ID,NG); + name.setAttribute(CORRESP,initials); + name.setText(fullName); + contrlSrc.addContent(name); + + } else { + System.out.println(" Need to deal with 2nd time use.\n"+ + "Check to see if same editor & same date.\n" + + "Create new editor or date-range."); + } + + } + + /** + *+ * This method returns an array of strings that contains 1. the opening string of the header, such as + * "Bibliographic Record for", and 2. the text contain within each of its children elements, usually + * there are two of these a lang="tib" and a lang="eng", each one entered separately. The strings + * are stripped of extraneous paragraph markers and spaces using the {@link #cleanString} method. + * If it's an English title then it is enclosed in parentheses. + *
+ * + * @returnString[]
an array containing the different strings that are the parts
+ * of this header element. They are kept separate so that different styles can be
+ * applied to the opening text (bold) and the title contents (bold-italic).
+ */
+ public String[] getHeadStrings()
+ {
+ Vector strs = new Vector();
+ Iterator children = head.getContent().iterator();
+ while(children.hasNext()) {
+ Object child = children.next();
+
+ if(child instanceof org.jdom.Text)
+ {
+ String t = ((org.jdom.Text)child).getText();
+
+ if(t != null)
+ {
+ t = cleanString(t);
+ if(t.length()>0 && !t.equals(" ")) strs.add(t);
+ }
+
+ } else if(child instanceof org.jdom.Element)
+ {
+ org.jdom.Element e = (org.jdom.Element)child;
+ if(e.getAttributeValue(LANG).equalsIgnoreCase(ENG)) {
+ strs.add("(" + cleanString(e.getText()) + ")");
+ } else {
+ strs.add(cleanString(e.getText()));
+ }
+ }
+ }
+ return TiblEdit.toStringArray(strs);
+ }
+
+ /**
+ * + * This method returns a string array of the sources used in creating this master document. + * These sources (for now -- this may change) are included within the controlInfo metadata for the + * text in a respStmt with n="source". It contains a Resp element with Source Records as the label and then + * a series of Name elements with their ID attribute set to their sigla and their content set to the full + * name of the source xml document (no path name). In the case of the master editor, the ID is set to Ng and + * the corresp attribute is set to the editor's initials. This serves to connect all the various pieces of information to + * a particular source by using their corresp attribute. The corresp attribute is an IDREF, which means its + * value must match the value for another element's ID. Thus, all uses of the corresp="Tk" not only identify + * the piece of information as belonging to the gTing skyes edition but also link each use with the name + * of the actual source file or the Tk Tibbibl record. In the case of the editor, their is a double IDREF + * occuring. Each use of the Ng sigla refers to the Name element in the sources that has the ID "Ng" and + * the corresp = to the editor's initials. This refers to the Resp element above that has an ID of the editor's + * intials and contains his or her full name. + *
+ */ + public String[] getSources() + { + org.jdom.Element respSt = findElement(RESPSTM,N,"source"); + Iterator children = respSt.getChildren().iterator(); + Vector sources = new Vector(); + while(children.hasNext()) + { + org.jdom.Element child = (org.jdom.Element)children.next(); + if(child.getName().equals(NAME)) + { + String childText = child.getText(); + int xmlind = childText.indexOf(".bib.xml"); + if(xmlind > -1) { + sources.add(childText.substring(0,xmlind)); + } else { + sources.add(childText); + } + } + } + return TiblEdit.toStringArray(sources); + } + + /** + *+ * This creates a critical version of any title within a TitleDecl by adding a title element + * as its first child with a Corresp=Ng. It does this by cloning one of the existing title elements + * to get one with identical attribute values but changes the corresp attribute to Ng. It adds + * a Foreign element with Lang = "eng as part of this title's content for the translation. It + * also "cleans" the title of an Expan element, which were used to add editor's interpretations of + * standard abbreviations such as thaMd for thams cad. These are replaced with the original abbreviated form. + * Finally, it adds a Num element within the pagination that has an ID = Ng and contains the initals of the + * editor who is the source of this critical title. + *
+ * + * @param org.jdom.Element - the Title element that is to serve as the basis of the critical title. This is + * the element that is cloned to create the critical version. + * + * @param initials - the initials of the editor creating the critical title. + */ + public org.jdom.Element createCriticalTitle(org.jdom.Element el, String initials) + { + + org.jdom.Element app, contItem; + Object item; + parent = el.getParent(); // the tdecl + child =((org.jdom.Element)el.clone()).detach(); + String base = child.getAttributeValue(CORRESP); + if(base == null) { + base = findTitleListEd(parent); + el.setAttribute(CORRESP,base); + } + + child.setAttribute(CORRESP,NG); + child.setAttribute(TYPE,base); + if(child.getChild(FOREIGN) == null) { + child.addContent(new org.jdom.Element(FOREIGN)); + } + java.util.List children = child.getContent(); + Iterator it = children.iterator(); + contItem = null; + app = null; + while(it.hasNext()) { + item = it.next(); + if(item instanceof org.jdom.Element) { + contItem = (org.jdom.Element)item; + if(contItem.getName().equals(EXPAN)) { + String resp = contItem.getAttributeValue(RESP); + String abbr = contItem.getAttributeValue(ABBR); + if(resp == null) { resp = new String();} + String expanText = contItem.getText(); + app = newApp(resp,expanText); + app.getChild(RDG).setAttribute(WIT,base); + app.getChild(RDG).setText(abbr); + break; + } + } + } + if(contItem != null && app != null) { + children.set(children.indexOf(contItem),app); + } + if(parent != null) { + parent.getChildren().add(0,child); + } + + org.jdom.Element grandparent = parent.getParent(); + org.jdom.Element pagination = grandparent.getChild(PAGIN); // the normal way for a titleDiv other than titlelists + + if(pagination == null) { + if(grandparent.getName().equals(TIBL)) // then it's a chapter + { + pagination = parent.getChild(SRC); + } + } + + if(pagination != null) { + org.jdom.Element newSource = new org.jdom.Element(NUM); + newSource.setAttribute(CORRESP,NG); + newSource.setText(initials); + pagination.getContent().add(0,newSource); + } else { + System.out.println("No pagination element found in creating critical title of " + TiblEdit.outputString(parent)); + } + + return child; + } + + + /** + *+ * This method sets the master doxogrpahy elements within the IntellDecl section of the Tibbibl. + * It takes two strings the Tibetan doxographical statement the English version of that. These + * list the categories separated by colons and are supplied by the {@link DoxWindow}. The master + * doxography element with type = "category" and n = "0" is located or else inserted and its + * text is set to the Tibetan doxographical statement and a Foreign element is included within that + * containing the English translation of it. + *
+ * + * @param String - the Tibetan doxographical statement + * + * @param String - the English doxographical statement. + */ + public void setDoxography(String tibDox, String engDox) + { + org.jdom.Element masterDox, edDox; + masterDox = null; + edDox = null; + org.jdom.Element[] doxs = findElements(DOX); + for(int n=0;n+ * This method returns the normalized title of the text using the tibbibl's {@link TitleFactory}. + *
+ * + * @return String - the normalized title of this text. + */ + public String getNormalizedTitle() + { + // the title factory returns the title element, not the text.. + element = tf.getNormalizedTitle(); + if(element == null) {return new String();} + return cleanString(element.getText()); + } + + /** + *+ * This method takes a titledecl from a title list and finds the edition listed in the first titleitem element. + * Because the same version of a title could span many chapters in different editions, the Corresp attribute is + * not set for the title itself in a title list but is set on the individual titleItems. This method finds the first + * title item and returns the sigla contained in its corresp element so this can be assigned as the type attribute + * of the critical version of the title. (The type attribute of a critical title indicates its original source title.) + * + *
+ * + * @param org.jdom.Element - the title list's titledecl. + * + * @return String - the sigla of the edition that is the source for the title, derrived from the first titleitem element. + */ + public String findTitleListEd(org.jdom.Element tdecl) + { + org.jdom.Element tlist,titem; + String edSig; + tlist = tdecl.getParent(); + if(!tlist.getName().equals(TLIST)) {return null;} + titem = tlist.getChild(TITEM); + edSig = titem.getAttributeValue(CORRESP); + return edSig; + } + + /** + *+ * This method takes a text string and a title element and uses it to insert an + * English translation for a title, by adding a Foreign element to the title element, setting + * its Lang=eng, and putting the text in its content. + *
+ * + * @param String - the text of the translation + * @param org.jdom.Element - the Title element (lang=tib) that contains the title being translated. + */ + public void addTranslation(String text, org.jdom.Element el) + { + if(el == null || el.getName().equals(NO_ELEM)) {return;} + org.jdom.Element foreign = el.getChild(FOREIGN); + if(foreign == null) { + System.out.println("Foreign is null: \n" + TiblEdit.outputString(el)); + foreign = new org.jdom.Element(FOREIGN); + foreign.setAttribute((org.jdom.Attribute)LANG_ENG.clone()); + el.addContent(foreign); + } + foreign.setText(text); + } + + /** + *+ * This method takes a Title element, a sigla, and a pagination and creates a new + * edition title within a particular TitleDecl. The element is one of the future siblings of the + * new edition title and is cloned to create one with identical attributes. The corresp value of the + * clone is then changed to the new sigla, children and text are removed, and the element is added + * to the active list of the TitleDecl's children. The pagination is located and a corresponding + * Num element is added with the corresp=sigla set and the text set to the given pagination. The + * resulting title element is then returned. + * + * THIS IS A TEMPORARY ADHOC FIX SO EDITORS CAN DEAL WITH EOC TITLES JUST LIKE OTHER TITLES + * One exception is if the new edition title is an EOC title + * to be added to a title list. In this case, the title is added to the titledecl as usual, but the + * pagination is included in a separate titleItem with a blank designation. This is a questionable practice + * because the notion of critically editing EOC titles is a contradition. The way we mark up EOC titles + * they are by nature variants, differences between them are catalogued by creating a new TitleList. But + * some of the title lists could be collapsed by considering them as variants on a critical title... + * The approach for this needs to be contemplated and fixed. Until then, they are treated like all other + * titles, and new edition titles added record their pagination in a separate title item element. + * + *
+ * + * @param org.jdom.Element - the title element to be cloned. + * @param String - the sigla of the new title element. + * @param String - the pagination of the new title. + * + * @return org.jdom.Element - the new edition title with corresp=sigla that is a sibling of the originally given title element. + */ + public org.jdom.Element addTitle(org.jdom.Element elem, String sigla, String pagination) + { + org.jdom.Element parent, grandparent, pagin, returnElem; + parent = elem; + if(elem.getName().equals(TITLE)) { + parent = elem.getParent(); + } else { + elem = parent.getChild(TITLE); + } + java.util.List children = parent.getChildren(TITLE); + java.util.List allChildren = parent.getChildren(); + elem = ((org.jdom.Element)elem.clone()).detach(); + elem.setAttribute(CORRESP,sigla); + elem.removeAttribute(TYPE); + elem.removeChildren(); + elem.setText(" "); + int tIndex = (children.size()>0?allChildren.indexOf(children.get(children.size()-1)):allChildren.size()-1); + allChildren.add(tIndex+1,elem); + returnElem = elem; + + grandparent = parent.getParent(); + if(grandparent != null) + { + if(grandparent.getName().equals(TDIV)) { // either its a title div + + pagin = grandparent.getChild(PAGIN); + if(pagin == null) { + System.out.println("Can't find pagination while inserting title element for:\n" + + TiblEdit.outputString(grandparent) +"\n Adding directly to this element"); + pagin = grandparent; + } else { + elem = new org.jdom.Element(NUM); + elem.setAttribute(CORRESP,sigla); + elem.setText(pagination); + pagin.addContent(elem); + } + + } else if(grandparent.getName().equals(TLIST)) { // or a title list + + parent = new org.jdom.Element(TITEM); + parent.setAttribute(CORRESP,sigla); + child = new org.jdom.Element(DESIG); + String[] specs = {"Which chapter in the " + sigla + " edition of the text is the source for this title?", + "Enter Chapter Number",JOP_INFO}; + String sectionNum = TiblEdit.promptInput(specs); + child.setText(sectionNum); + parent.addContent(child); + child = new org.jdom.Element(PAGIN); + child.setText(pagination); + parent.addContent(child); + grandparent.addContent(parent); + + } else if(grandparent.getName().equals(TIBL)) { // or else it's a chapter TIBBIBL + + children = parent.getChildren(); + pagin = parent.getChild(SRC); + int srcIndex = children.indexOf(pagin); + if(srcIndex > -1) { + parent.removeContent(elem); + parent.getChildren().add(srcIndex,elem); + } else { + System.out.println("Could not find source in chapter title decl: " + TiblEdit.outputString(parent)); + pagin = new org.jdom.Element(SRC); + parent.addContent(pagin); + } + child = new org.jdom.Element(NUM); + child.setAttribute(CORRESP,sigla); + child.setText(pagination); + pagin.addContent(child); + } + } + return returnElem; + } + + /** + *+ * This returns the text of a title element as it is displayed in the {@link TextPane}. It gets this in the + * same way the text pane does by using a {@link TitleParser} that finds the constituent parts of a title and + * determines which are to be displayed. For instance, if there is an app element, it displays only the text of + * the Lem child (i.e., the main reading). + *
+ * + * @param org.jdom.Element - the title whose text is desired. + * + * @return String - the display text for that title element. + */ + public String getTitleText(org.jdom.Element title) + { + TitleParser tparse = new TitleParser(title); + return tparse.getTitleText(); + } + + /** + *+ * This method takes a title element, a string of selected text, and an integer indicating the offset from + * the start of the text's title where the apparatus element is to be inserted. It then uses a + * {@link TitleParser} to figure out the display text of the title, and with the offset integer determines + * where in the title the apparatus element is to be inserted. It receives that part from the TitleParser, splits it, + * and adds the app element. If all succeeds, the app element is then returned. + *
+ * + * @param org.jdom.Element - the title in which the app is to be inserted. + * @param String - the text selected in the {@link TextPane} that indicates where the app is to be inserted. + * @param int - the offset from the beginning of the text's display title, where the insertion point is. + * + * @return org.jdom.Element - the app element that has been successfully inserted or null if unsuccessfull. + */ + public org.jdom.Element insertApp(org.jdom.Element title, String selText, int offset) + { + // if title does not have corresp == to NG then return + // can only add aps to critical versions of the title + if(!title.getAttributeValue(CORRESP).equals(NG)) { + System.out.println("The Title's corresp attribute does not equal Ng!\n" + + TiblEdit.outputString(title)); + return null; + } + + TitleParser tparser = new TitleParser(title); + if(tparser.isAppInsertable(offset, selText)) + { +System.out.println("selected text is: " + selText); + java.util.List children = title.getContent(); + Vector newContents = new Vector(); + Object child = tparser.getItemAt(offset); + String text = tparser.getTextAt(offset); +System.out.println("TExt at title offset is: " + text); + int index = text.indexOf(selText); + + String sigla = title.getAttributeValue(TYPE); + if(sigla == null) { sigla = title.getAttributeValue(CORRESP);} + if(sigla == null) { sigla = NG;} + + if(child != null && index > -1 && (index + selText.length())<=text.length()) { + int childIndex = children.indexOf(child); + if(childIndex > -1) { + newContents.add(new org.jdom.Text(text.substring(0,index-1)+" ")); + org.jdom.Element app = newApp(sigla,selText); + newContents.add(app); + newContents.add(new org.jdom.Text(text.substring(index+selText.length()))); + children.remove(child); + children.addAll(childIndex,newContents); + return app; + } else { + System.out.println("Couldn't locate child in content list of element!"); + System.out.println("Title: " + TiblEdit.outputString(title)); + System.out.println("Child: " + child.toString()); + } + + } else { + System.out.println("Could not split up text run properly! in Tib Doc insertApp! Or child was null"); + System.out.println("Title: " + TiblEdit.outputString(title)); + System.out.println("Text run: " + text); + System.out.println("Sel text: " + selText); + System.out.println("Index of: " + index); + System.out.println("Child: " + child); + } + } else { + System.out.println("Tparser rejected insert App!"); + } + + return null; + } + + /** + *+ * This method removes an existing App element, replacing it with the text of its lemma or main reading child. + *
+ * + * @param org.jdom.Element - the app to be removed. + */ + public void removeApp(org.jdom.Element appToRemove) + { + parent = appToRemove.getParent(); + if(parent == null) {return;} + int index = parent.getContent().indexOf(appToRemove); + element = appToRemove.getChild(LM); + String text = new String(" "); + if(element != null) {text = element.getText();} + System.out.println("Replacing app with " + text); + parent.getContent().set(index,new org.jdom.Text(text)); + } + + /** + *+ * This method is called when the Normalized title and/or translation is changed. It locates the text's + * main Head element, which contains the text's header with its title, and changes the content of the + * two title elements (tib and eng) in the header to accurately reflect the modified normalized title + * and translation. + *
+ */ + public void updateTextHeader() + { + org.jdom.Element head, normTitle, foreign; + org.jdom.Element[] heads; + + normTitle = tf.getNormalizedTitle(); + foreign = normTitle.getChild(FOREIGN); + heads = tf.getHeaderTitles(); + if(heads != null) { + heads[0].setText(normTitle.getText()); + if(heads.length>1) { + heads[1].setText(foreign.getText()); + } else { + element = new org.jdom.Element(TITLE); + element.setAttribute(TYPE,TEXT_HEAD); + element.setAttribute(LANG,ENG); + element.setText(foreign.getText()); + heads[1].getParent().addContent(element); + } + } else { + head = findElement(HEAD); + element = new org.jdom.Element(TITLE); + element.setAttribute(TYPE,TEXT_HEAD); + element.setAttribute(LANG,TIB); + element.setText(normTitle.getText()); + head.addContent(element); + element = new org.jdom.Element(TITLE); + element.setAttribute(TYPE,TEXT_HEAD); + element.setAttribute(LANG,ENG); + element.setText(foreign.getText()); + head.addContent(element); + } + + } + + // Static Methods + + /** + *+ * This static method is used to clean up an string derrived from XML content that may have paragraph returns + * in the middle of it and preceding or trailing spaces, etc. It replaces all the "\n" with spaces and then + * reduces all double spaces to single spaces as well as trimming the string of preceding or following spaces. If null, + * is sent to this method, it returns an empty String. + *
+ * + * @param String - the text to be cleaned. + * + * @return String - the clean text. + */ + public static String cleanString(String text) + { + if(text != null) { + text = text.replace('\n',' '); + StringTokenizer parts = new StringTokenizer(text," "); + text = new String(); + while(parts.hasMoreTokens()) { + String word = parts.nextToken(); + if(word != null && !word.equals(" ")) { + text += word; + if(parts.hasMoreTokens()) { text += " "; } + } + } + } else { + text = ""; + } + return text; + } + + /** + *+ * This static method is used to convert standard lists, such as Vectors, into arrays of org.jdom.Elements. This + * is useful because the getContent method of Element returns a List and in iteration each item must be cast + * back to an Element. This method returns a fixed array of Elements that do not require such casting. + *
+ * + * @param java.util.List - the list of content or children of an element. + * + * @return org.jdom.Element[] - the array of element children derrived from the list. + */ + public static org.jdom.Element[] toElementArray(java.util.List childs) + { + Object[] objs = childs.toArray(); + org.jdom.Element[] out = new org.jdom.Element[objs.length]; + for(int n=0; n+* TibDoc has a single constructor that takes a root element for the document. +*
+* +* @param org.jdom.Element - the new TibDoc's root element. +*/ + public TibDoc(org.jdom.Element rootElement) + { + super(rootElement); + setHead(); + setFactories(); + setDocType(new DocType(TIBL,"..\\bin\\xtibbibl2.dtd")); + org.jdom.Attribute idAt = getRootElement().getAttribute(ID); + if(idAt != null && (idAt.getValue() == null || idAt.getValue().equals(""))) { + idAt.detach(); + } + } +} diff --git a/source/org/thdl/tib/bibl/TibFrame.java b/source/org/thdl/tib/bibl/TibFrame.java new file mode 100644 index 0000000..0ac7412 --- /dev/null +++ b/source/org/thdl/tib/bibl/TibFrame.java @@ -0,0 +1,876 @@ +/* +The contents of this file are subject to the THDL Open Community License +Version 1.0 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License on the THDL web site +(http://www.thdl.org/). + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +License for the specific terms governing rights and limitations under the +License. + +The Initial Developer of this software is the Tibetan and Himalayan Digital +Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL. +All Rights Reserved. + +Contributor(s): ______________________________________. +*/ + +package org.thdl.tib.bibl; + +import java.awt.Event; +import java.awt.event.*; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.io.File; +import java.util.Vector; +import java.util.Iterator; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.event.*; + + /** + *+ * TibFrame is the view for the {@link TiblEdit} program. TiblEdit is the controller. + * {@link TibDoc}, or {@link TiblEdit#tibbibl} in its instantiation, is the data model. + * TibFrame mainly utilizes a {@link TextPane} (an extension of JTextPane) as its main + * view window, but also allows split screens with a {@link DiacriticPanel} on the left and/or + * a {@link TibTable} at the bottom. + *
+ */ + +public class TibFrame extends JFrame implements CaretListener, TibConstants +{ + // Attributes + private TiblEdit controller; + + // Frame Attributes + private JMenu fileMenu, editMenu, insertMenu, provMenu, viewMenu; + // File Menu items + private JMenuItem openItem, closeItem, saveItem, saveAsItem, exportItem, exitItem; + + // Edit Menu items + protected JMenuItem cutItem, copyItem, pasteItem, editTransItem, editNormItem, + removeAppItem, removeTitleItem, removeEditionItem; + + // Insert menu items + private JMenuItem critTitleItem, edTitleItem, variantItem, insertEdItem, insertDiscItem; + + // View Menu items + private JCheckBoxMenuItem diacItem, edConsultItem; + private JMenuItem masterIDItem, userIDItem, aboutItem; + private JMenuItem[] recentFileItems; + //private JMenuItem authorItem, audienceItem, redactorItem, translatorItem, concealerItem, revealerItem; + + private JPanel contentPanel; + private JComponent rightSp, leftSp, bottomSp, topSp; + private JSplitPane horizontalSplit, verticalSplit; + private TextPane tp; + private DiacriticPanel dp; + private TibTable tibTable; + Vector styleElements; + + // Initialization + /** + *+ * This is the initialization method for the TibFrame. The TibFrame is the view for + * this program, for which a {@link TiblEdit} object is the controller and + * a {@link TibDoc} is the data model. This method establishes a file menu, + * an edit menu, an view menu, and an insert menu. Its content pane is set to a + * JScrollPane with a {@link TextPane} as its view. + *
+ */ + protected void init() + { + Toolkit xKit = getToolkit(); + Dimension wndSize = xKit.getScreenSize(); + setBounds(wndSize.width/16, wndSize.height/16, + 7*wndSize.width/8, 7*wndSize.height/8); + addWindowListener(new XWindowHandler()); + addComponentListener(new XComponentHandler()); + + // TextPane content pane + tp = new TextPane(controller); + EditorKit ekit = tp.getEditorKit(); + Action[] actions = ekit.getActions(); + + // MenuBar + JMenuBar menuBar = new JMenuBar(); + setJMenuBar(menuBar); + + // File Menu + fileMenu = new JMenu(FILE); + openItem = fileMenu.add(new FileAction(OPENFILE,this)); + openItem.setAccelerator(KeyStroke.getKeyStroke('O',Event.CTRL_MASK)); + openItem.setFont(MENU_FONT); + openItem.setEnabled(true); + + closeItem = fileMenu.add(new FileAction(CLOSEFILE,this)); + closeItem.setAccelerator(KeyStroke.getKeyStroke('W',Event.CTRL_MASK)); + closeItem.setFont(MENU_FONT); + closeItem.setEnabled(false); + + saveItem = fileMenu.add(new FileAction(SAVE,this)); + saveItem.setAccelerator(KeyStroke.getKeyStroke('S',Event.CTRL_MASK)); + saveItem.setFont(MENU_FONT); + saveItem.setEnabled(false); + + fileMenu.addSeparator(); + + recentFileItems = new JMenuItem[RECENT_FILE_SIZE]; + for(int n=0;n+ * This method returns the controller for this view. + *
+ * + * @return TiblEdit - the controller. + */ + public TiblEdit getController() + { + return controller; + } + + /** + *+ * This method sets the list of recent files in the file menu + *
+ * + * @param recent - A Vector of the recent files from the controller. + */ + public void setRecentFiles(Vector recent) + { + int n = 0; + for(Iterator it=recent.iterator();it.hasNext();) + { + final File file = (File)it.next(); + if(n == RECENT_FILE_SIZE) {break;} + JMenuItem fileItem = recentFileItems[n++]; + fileItem.setText(file.getName()); + ActionListener al[] = fileItem.getActionListeners(); + if(al != null && al.length >0) {fileItem.removeActionListener(al[0]);} + fileItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) + { + controller.openFile(file); + } + }); + fileItem.setVisible(true); + fileItem.setEnabled(true); + } + + for(;n+ * This returns the position of the caret within the {@link TextPane} that is + * the main text view for the program. + *
+ * + * @return int - the position of the caret. + */ + public int getCaretPosition() + { + return tp.getCaret().getDot(); + } + + // Helper methods + /** + *+ * This method is called by the controller when a file is opened. It serves to + * enable or disable the appropriate menu commands. Open is disabled, and + * close, save, view titles, add crit title, add ed title, and view editions consulted + * are turned on. + *
+ */ + public void fileOpened() + { + setTitle(PROG_NAME+controller.getCurrentFile().getName()); + openItem.setEnabled(false); + closeItem.setEnabled(true); + saveItem.setEnabled(true); + critTitleItem.setEnabled(true); + edTitleItem.setEnabled(true); + edConsultItem.setEnabled(true); + copyItem.setEnabled(true); + cutItem.setEnabled(true); + pasteItem.setEnabled(true); + editTransItem.setEnabled(true); + editNormItem.setEnabled(true); + masterIDItem.setEnabled(true); + insertEdItem.setEnabled(true); + removeEditionItem.setEnabled(true); + insertDiscItem.setEnabled(true); + for(int n=0;n+ * This method is called (maybe?) when the cursor is on a title. It enables the add + * critical title menu option. (May be deprecated?) + *
+ */ + public void titleSelected() + { + critTitleItem.setEnabled(true); + } + + /** + *+ * This method is called (maybe?) when cursor is on something other than a title. It disnables the add + * critical title menu option. (May be deprecated?) + *
+ */ + public void titleNotSelected() + { + critTitleItem.setEnabled(false); + } + + /** + *+ * This method displays a {@link TibTable} as the bottom half of a split screen with the {@link TextPane} + * This particular table displays the editions consulted for the formation of the master record + * by displaying the information in the text's tibiddecl element. To do so it uses {@link TibTable(IDFactory) TibTable constructor} + * that takes an {@link IDFactory} retrieved from the {@link TibDoc}. It then calls {@link #showTable(TibTable) TibTable} + * method. + *
+ */ + public void showEditions() + { + if(controller.getTibDoc() == null) {return;} + tibTable = new TibTable(controller.getTibDoc().getIDFactory()); + showTable(tibTable); + } + /** + *+ * This method hides any table that is displaying at the bottom of the {@link TextPane}. The first + * table that used this was the edition's consulted table, but it will close any table including an apparatus + * table that is displaying at the bottom of the screen. + *
+ */ + + public void hideEditions() + { + topSp = new JScrollPane(tp); + if(horizontalSplit == null) { + setContentPane(topSp); + show(); + + } else { + int horizLoc = horizontalSplit.getDividerLocation(); + horizontalSplit.setRightComponent(topSp); + show(); + horizontalSplit.setDividerLocation(horizLoc); + } + show(); + verticalSplit = null; + } + + /** + *+ * This method creates a split screen with a {@link DiacriticPanel(TibFrame) DiacriticPanel} + * on the left and the main {@link TextPane} on the right. + *
+ */ + public void showDiacritics() + { + dp = new DiacriticPanel(this); + rightSp = new JScrollPane(dp); + JComponent comp; + if(verticalSplit == null) { + leftSp = new JScrollPane(tp); + comp = leftSp; + } else { + comp = verticalSplit; + } + horizontalSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,rightSp,comp); + setContentPane(horizontalSplit); + show(); + double loc = 0.1D; + horizontalSplit.setDividerLocation(loc); + } + + /** + *+ * This method hides the {@link DiacriticPanel} that is displayed on the left of + * the split screen. + *
+ */ + public void hideDiacritics() + { + JComponent comp; + if(verticalSplit == null) { + comp = tp; + } else { + comp = verticalSplit; + } + rightSp = new JScrollPane(comp); + setContentPane(rightSp); + show(); + horizontalSplit = null; + } + + /** + *+ * This method displays a {@link TibTable} underneath the {@link TextPane}. It takes a + * {@link TibTable} as its parameter and depending on the value of its {@link TibTable#getType() type} + * inserts either an JTable with the editions consulted or it retrieves an {@link TibTable#getAppPanel() specific + * JPanel} that has a table with an apparatus' info and control buttons. + *
+ * + * @param TibTable the TibTable object that contains the tabular information to be displayed. + */ + public void showTable(TibTable tt) + { + JSplitPane tableSplit = new JSplitPane(); + if(tt.getType() == TibTable.APP) { + edConsultItem.setSelected(false); + tt.addObserver(controller); + tableSplit = tt.getAppPanel(); + bottomSp = tableSplit; + } else { + bottomSp = new JScrollPane(tt.getTable()); + } + topSp = new JScrollPane(tp); + verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,topSp,bottomSp); + if(horizontalSplit == null) { + setContentPane(verticalSplit); + show(); + } else { + int horizLoc = horizontalSplit.getDividerLocation(); + horizontalSplit.setRightComponent(verticalSplit); + show(); + horizontalSplit.setDividerLocation(horizLoc); + } + double loc = 0.80D; + verticalSplit.setDividerLocation(loc); + tableSplit.setDividerLocation(loc); + } + + /** + *+ * This method is called if the insert variant option is chosen from the insert menu. Variant readings + * are displayed in the {@link TextPane} with a yellow background and are determined by being marked up + * within an app element. When inserting a new variant, the app element was not originally there so the + * selected area does not have a yellow background. This method sets the background of the selected area + * to yellow until the insertion is complete and the TextPane can be redisplayed. + *
+ */ + public void displayNewApp() + { + int start = tp.getSelectionStart(); + int len = tp.getSelectedText().length(); + Style variant = tp.getStyle(TextPane.VARIANT); + tp.getStyledDocument().setCharacterAttributes(start,len,variant,false); + } + + /** + *+ * This method displays all the variations of text titles found in a {@link TibDoc}. It takes the + * TibDoc's {@link TitleFactory} and uses its {@link TitleFactory#getAllTitles() getAllTitles} method + * to retrive a vector of {@link ElementStyle ElementStyles}. It also adds a text header at the top + * and depending on the {@link TiblEdit#mode mode} of the controller (i.e., whether it is inserting a + * new title or translation, etc.) adds appropriate prompts. It then calls the {@link TextPane#setTextPane(Vector) TextPane's setTextPane(Vector)} + * method with the vector of StyleElements and this displays the information. That setTextPane method + * returns an {@link ElementList} which is a list of org.jdom.Elements with their associated positions in + * the TextPane (start and end) so that when the caret is positioned somewhere in the TextPane the controller + * can find the associated element and make the appropriate options available. + *
+ * + * @param TitleFactory - The TibDocs TitleFactory object for retrieving title information + * + * @return ElementList - The ElementList returned by the TextPane once its document is set. + * + */ + public ElementList showTitles(TitleFactory tf) + { + int presCaretPos = tp.getCaretPosition(); + if(presCaretPos < 0) {presCaretPos = 0;} + + styleElements = new Vector(); + + // Do the Text's Header Element as the documents general header + String[] headStrings = tf.getHeadStrings(); + + if(headStrings == null) { + + styleElements.add(new ElementStyle("No Head Element Found\n\n",TextPane.TEXT_HEAD,NO_ELEM)); + + } else { + styleElements.add(new ElementStyle(headStrings[0]+" ",TextPane.TEXT_HEAD,NO_ELEM)); + + if(headStrings.length>1) { + for(int n=1;n+ * This constructor simply takes a title as the corresponding JFrame contructor. + *
+ * + * @param String - the frame's title. + */ + public TibFrame(String title) + { + super(title); + init(); + } + + /** + *+ * This constructor takes both a title and a {@link TiblEdit} object that is its controller. + * It first calls JFrame's title constructor, then {@link #setController(TiblEdit) the setController} method + * and then the {@link #init()} method. + *
+ */ + public TibFrame(String title, TiblEdit app) + { + super(title); + setController(app); + init(); + } + + // Main for testing + + public static void main(String[] args) + { + } + + // Listeners + /** + *+ * This implementation of the CaretListener interface calls the controller's + * {@link TiblEdit#checkCaretPosition(String) checkCaretPosition} method with the type of {@link TibConstants#AP AP} + * to see if an appartatus element is insertable. If so, then it turns on the insert variant reading + * menu item. If not, that item is turned off. + *
+ * + * @param CaretEvent - the required parameter of this abstract method. It is not used here. + */ + public void caretUpdate(CaretEvent ce) + { + boolean canInsertAp = controller.checkCaretPosition(AP_CHECK); + if(canInsertAp) { + variantItem.setEnabled(true); + } else { + variantItem.setEnabled(false); + } + + if(controller.checkCaretPosition(ED_TITLE_REM)) { + removeTitleItem.setEnabled(true); + } else { + removeTitleItem.setEnabled(false); + } + } + + // SubClasses Event Handlers + /** + *+ * The inner class, XWindowHandler, extends the WindowAdapter and is used for the closing of the frame. + * It is added to the TibFrame in its {@link #init} method. + *
+ */ + + /** + *+ * When the TibFrame is closed, the program ends. The window is disposed. The controller's + * {@link TiblEdit#writePrefs() writePrefs()} method is called, and the system is exited. + *
+ * + * @param WindowEvent - the required parameter for this abstract method. + */ + public class XWindowHandler extends WindowAdapter + implements TibConstants + { + + public void windowClosing(WindowEvent e) + { + e.getWindow().dispose(); + controller.exit(); + } + } + public class XComponentHandler extends ComponentAdapter + { + + public void ComponentResized(ComponentEvent ce) + { + show(); + } + } + + +} diff --git a/source/org/thdl/tib/bibl/TibTable.java b/source/org/thdl/tib/bibl/TibTable.java new file mode 100644 index 0000000..ee8a9e7 --- /dev/null +++ b/source/org/thdl/tib/bibl/TibTable.java @@ -0,0 +1,632 @@ +/* +The contents of this file are subject to the THDL Open Community License +Version 1.0 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License on the THDL web site +(http://www.thdl.org/). + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +License for the specific terms governing rights and limitations under the +License. + +The Initial Developer of this software is the Tibetan and Himalayan Digital +Library (THDL). Portions created by the THDL are Copyright 2001-2003 THDL. +All Rights Reserved. + +Contributor(s): ______________________________________. +*/ + +package org.thdl.tib.bibl; + +import java.awt.*; +import java.awt.event.*; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.table.*; +import org.jdom.*; + +/** +* This element is a wrapper element for a JTable that sets up two kinds of tables for editing a Tibbibl--one for +* displaying various editions and one for displaying alternative readings. +*/ + +public class TibTable extends Observable implements TibConstants, ActionListener +{ + // Attributes + private JTable theTable; + private TibTableModel ttm; + private org.jdom.Element app, pagination; + private IDFactory idf; + private Hashtable pageHash; + private int type; + private boolean editable; + private int mainrow; + private TibTableCellRenderer ttcr; + + + // Constants + public static int EDS_CONSULTED = 0; + public static int APP = 1; + + // Header Constants + private static String ED_NAME_HEAD = "Edition Name"; + private static String ED_HEAD = "Edition"; + private static String VOL_HEAD = "Volume"; + private static String TEXT_HEAD = "Text No."; + private static String PAGE_HEAD = "Pagination"; + private static String READING = "Reading"; + private static String ID_HEAD = "Id. No."; + private static String IS_MAIN = "Main Reading"; + + public static String MAINED = "Set Main Edition"; + public static String REMOVE_RDG = "Remove Reading"; + public static String SUB = "Done"; + public static String CANC = "Cancel"; + + private static String[] DEFAULT_HEADS = {ED_NAME_HEAD, ID_HEAD,VOL_HEAD,PAGE_HEAD}; + private static String[] ED_CON_HEADS = {ED_HEAD,TEXT_HEAD,VOL_HEAD,PAGE_HEAD}; + private static String[] APP_HEADS = {ED_HEAD,VOL_HEAD,PAGE_HEAD,READING,IS_MAIN}; + + // Accessor methods + public void setTable(JTable jt) + { + theTable = jt; + ttcr = new TibTableCellRenderer(); + ttcr.setMainRow(getMainRow()); + String st = new String(); + jt.setDefaultRenderer(st.getClass(),ttcr); + } + + public JTable getTable() + { + return theTable; + } + + public void setTibTableModel(TibTableModel ttm) + { + this.ttm = ttm; + } + + public TibTableModel getTibTableModel() + { + return ttm; + } + + public void setApp(org.jdom.Element ap) + { + app = ap; + } + + public org.jdom.Element getApp() + { + return app; + } + + public void setIDFactory(IDFactory idf) + { + if(idf == null) {System.out.println("IDF is null in TibTable!");} + this.idf = idf; + } + + public IDFactory getIDFactory() + { + return idf; + } + + public void setPagination(org.jdom.Element page) + { + pagination = page; + pageHash = new Hashtable(); + Iterator it = page.getChildren(NUM).iterator(); + while(it.hasNext()) + { + org.jdom.Element numChild = (org.jdom.Element)it.next(); + String ed = numChild.getAttributeValue(CORRESP); + String pageNums = TibDoc.cleanString(numChild.getText()); + pageHash.put(ed,pageNums); + } + } + + public org.jdom.Element getPagination() + { + return pagination; + } + + public Hashtable getPageHash() + { + return pageHash; + } + + public void setType(int type) + { + this.type = type; + } + + public int getType() + { + return type; + } + + public void setMainRow() + { + int oldrow = getMainRow(); + int row = theTable.getSelectedRow(); + String firstCell = (String)theTable.getValueAt(row,0); + if(firstCell == null || firstCell.equals("")) {return;} + setMainRow(row); + ttcr.setMainRow(row); + ttm.setValueAt(new Boolean(false),oldrow,4); + ttm.setValueAt(new Boolean(true),row,4); + theTable.repaint(); + } + + public void setMainRow(int mr) + { + mainrow = mr; + } + + public int getMainRow() + { + return mainrow; + } + + public String[] getHeaders() + { + if(type == EDS_CONSULTED) { + return ED_CON_HEADS; + } else if(type == APP) { + return APP_HEADS; + } + return DEFAULT_HEADS; + } + + // Helper methods + /** + *+ * This is an "overriding" of the setTable(JTable jt) accessor, which simply sets the table variable + * to the given parameter. This method on the other hand sets the table + * depending on the {@link #type} of TibTable this is. If this TibTable is constructed + * solely with an {@link IDFactory}, then it is an {@link #EDS_CONSULTED} type. If it is + * constructed with an Apparatus element, IDFactory, and a Pagination element, then it + * is an {@link #APP}, or apparatus, type. This method will construct the table model + * accordingly. + *
+ */
+ public void setTable()
+ {
+ if(type == EDS_CONSULTED) {
+
+ Vector eds = idf.getEditionsConsulted();
+ Object[][] tdata = new Object[eds.size()][ED_CON_HEADS.length];
+ int e = 0;
+ Iterator it = eds.iterator();
+ while(it.hasNext()) {
+ String ed = (String)it.next();
+ if(ed.equals(NG)) {continue;}
+ tdata[e][0] = ed;
+ tdata[e][1] = idf.getTextNum(ed);
+ tdata[e][2] = idf.getVolNum(ed);
+ tdata[e][3] = idf.getPagination(ed);
+ for(int n=0; n<4; n++) {
+ if(tdata[e][n] == null) {tdata[e][n] = new String("");}
+ }
+ e++;
+ }
+ setTibTableModel(new TibTableModel(tdata,ED_CON_HEADS));
+ setTable(new JTable(getTibTableModel()));
+
+ } else if (type == APP) {
+ doAppTable();
+ }
+
+ }
+
+ public void doAppTable()
+ {
+ Vector eds = new Vector(idf.getEditionsConsulted());
+ java.util.List readings = getApp().getChildren();
+ Object[][] tdata = new Object[eds.size()+1][APP_HEADS.length];
+ for(int r=0;r
+ * This is the main window or the view for the TiblEdit
class, which acts
+ * as the controller.
+ *
+ * This is a reader for XML files that returns a {@link TibDoc}. + *
+ */ + XMLReader xreader = new XMLReader(); + + /** + *+ * This instantiation of XMLOutputter is used for writing the XML files. It is different + * from the static instantiation of the same class, the variable {@link #xop}, that is used + * for debugging purposes to print out string versions of elements. + *
+ */ + XMLOutputter XMLOut = new XMLOutputter(""); + + /** + *+ * This is the folder where the data, or unprocessed master catalog records, are held. + *
+ */ + String dataDirectory; + + /** + *+ * This is the folder where the files are written to. + *
+ */ + File outDirectory; + + /** + *
+ * This is the directory currently being worked in, is updated as user navigates to different
+ * folders with the JFileChooser
.
+ *
+ * This is the presently open file that is being worked on. + *
+ */ + File currentFile; + + + /** + *+ * This is the list of recently opened files. + *
+ */ + Vector recent; + + /** + *+ * This is the name of the file which is changed when the master ID is changes + *
+ */ + String fileName; + + /** + *+ * This is the {@link TibDoc} that serves as the data model for the open file/text. + * It contains the XML tibbibl record that is presently being worked on. + *
+ */ + TibDoc tibbibl; + +/** +* The name of the editor using TiblEdit. This is entered +* the first time the program is run and thereafter stored in a preferences file. +* Once entered, it can be changed through the options menu. +*/ + private String editorsName; + +/** +* The initials of the editor using TiblEdit. This is entered +* the first time the program is run and thereafter stored in a preferences file. +* Once entered, it can be changed through the options menu. +*/ + private String editorsInitials; + +/** +* The present date formatted as yyyy-mm-dd, obtained from the operating system and stored +* as metadata in each XML file written. +*/ + private String todaysDate; +/** +*+* This is the file chooser object that will be modified in {@link #setFileChoose} so +* that it displays the text names instead of the file names when opening a file. +*
+*/ + private JFileChooser fc; + + /** + * These need to be documented. + */ + private boolean is_file_list; +/** +*
+* This ElementList
contains a list of elements that are displayed in
+* the {@link TextPane}. It connects the elements with the starting and ending position
+* of their displayed text so that when a selection of text is made the program can look
+* up the associated element in the element list. It is used to set the {@link #selected_element}
+* variable.
+*
+* This is the element that is found at the caret position or the selected text within +* the {@link TextPane}. It is then processed in various methods depending on the +* choice selected. It is set by this object's {@link #mouseClicked} method or else by +* the TextPane itself when a menu option is chosen. +*
+*/ + private org.jdom.Element selected_element; +/** +*+* These variables are generic JDOM Elements for parent, grandparent, element (or self), +* and child. They are used throughout the program. +*
+*/ + org.jdom.Element parent, grandparent, element, child; + +/** +*+* This is a {@link TextPane} that is gotten from {@link TibFrame} and is used in methods for inserting elements. +*
+*/ + TextPane tp; +/** +*+* This is the current display/functioning mode of the program. It has four settings: +*
+* This is a variable that counts how many files have been outputted that have no +* file name. This is just in case something goes wrong and the file needs a name. +* Each time such a file is written, this is appended to the generic name and augmented one +* so the next file will have a unique name. It appears below, but the situation for its +* use never occurs. FIX! +*
+*/ + int outCount; + +/** +*This is the Thread
used to run the splash screen while the program
+* loads.
+*
+* This variable tells whether a text has been saved or not +*
+*/ + boolean hasBeenSaved; + + Hashtable edNames; + + Hashtable fileHash; + + TibDialog editorsDialog; + + // For testing and debugging purposes. + /** + *+ * This static instanciation of an {@link org.jdom.output.XMLOutputter} is used by + * the static method {@link #outputString}, to print XML mark-up for debugging + * purposes. + *
+ */ + public static XMLOutputter xop = new XMLOutputter(); + + + //init method + /** + *+ * The init method sets the {@link #dataDirectory}, {@link #currentDirectory}, + * and the {@link tibFrame} variables. It reads in preferences from {@link #readPrefData}, + * performs {@link #setDate} and {@link #setFileChooser}, and sets the {@link #mode} + * to {@link TibConstants@NORM}. + *
+ */ + public void init() + { + showSplash(); + for(int fxc=0; fxc<100000; fxc++) { int nfx = fxc; } + + setDate(); + // set up log output stream + File logDirectory = new File(DEFAULT_DIRECTORY + BIN_LOGIN); + if(!logDirectory.exists()) { + //System.out.println("Making log directory!"); + logDirectory.mkdir(); + } + int n = 1; + String logFileName = "Session_" + getDate() + "_" + n + ".txt"; + File logFile = new File(logDirectory, logFileName); + while(logFile.exists()) { + n++; + logFileName = "Session_" + getDate() + "_" + n + ".txt"; + logFile = new File(logDirectory, logFileName); + if(n>1000) {break;} + } + try { + FileOutputStream logFos = new FileOutputStream(logFile); + PrintStream logPs = new PrintStream(logFos, true); + System.out.println("Resetting System and Error out to: \n\t" + logFile.getPath()); + System.setOut(logPs); + System.setErr(logPs); + } catch (FileNotFoundException fnfe) { + System.out.println("File not found exception is opening log output stream: " + logFile.getName()); + } catch (SecurityException se) { + System.out.println("Security exception in assigning log output stream!"); + } + + dataDirectory = DEFAULT_DIRECTORY + DATA_DIRECTORY; + currentDirectory = new File(dataDirectory); + outDirectory = new File(DEFAULT_DIRECTORY + OUT_DIRECTORY); + tibFrame = new TibFrame(DEFAULT_HEADER, this); + + mode = NORM; + hasBeenSaved = false; + + editorsDialog = new TibDialog(tibFrame,EDITORS_INFO,EDITORS_INFO_SPECS); + editorsDialog.setSize(new Dimension(450,100)); + readPrefData(); + + tibFrame.setRecentFiles(recent); + + edNames = new Hashtable(); + edNames.put(NG,EDNAMES[0]); + edNames.put(TB,EDNAMES[1]); + edNames.put(TK,EDNAMES[2]); + edNames.put(DG,EDNAMES[3]); + edNames.put(BG,EDNAMES[4]); + edNames.put(KG,EDNAMES[5]); + + } + + /** + * This reads in the preferences from the preference file that is located in + * {@link TibConstants#DEFAULT_DIRECTORY} + {@link TibConstants#BIN} + + * {@link TibConstants#PREFS}. The main preferences that are stored in this file + * are: the {@link editorsInitials} and {@link editorsName}. + * + */ + public void readPrefData() + { + is_file_list = false; + recent = new Vector(); + File prefFile = new File((DEFAULT_DIRECTORY + BIN + PREFS)); + if(prefFile.exists()) + { + try + { + BufferedReader br = new BufferedReader(new FileReader(prefFile)); + String line = new String(); + while(br.ready()) { + line = br.readLine(); + int ind = line.lastIndexOf(PREFS_DELIM); + System.out.println("Init line read: {"+line+"} = " + + (line!=null?Integer.toString(line.length()):"null")); + if(line == null || line.indexOf("null")>-1 + || ind == -1 || ind>line.length()-2) + { + getEditorInfo(); + } else { + + if(line.indexOf(EDITORS_NAME)>-1) { + editorsName = line.substring(ind+1); + } else if (line.indexOf(EDITORS_INITIALS)>-1) { + editorsInitials = line.substring(ind+1); + } else if(line.indexOf(IS_FILE_LIST)>-1) { + String is_there = line.substring(ind+1); + if(is_there.equals(YES)) {is_file_list = true;} + } else if(line.indexOf(RECENT)>-1) { + String recentName = line.substring(ind+1); + recent.add(new File(recentName)); + if(recent.size()>RECENT_FILE_SIZE) {recent.remove(0);} + } + } + } + br.close(); + } + catch(IOException ioe) { + System.out.println("An io exception occurred while reading in data from the text list."); + System.out.println("The error was: " + ioe.getMessage() + " " + ioe.getClass().getName()); + } + } else { + getEditorInfo(); + } + + } + + /** + * This method is called if there is no editor information in the preference file. + * It uses a {@link TibDialog} with {@link TibConstants#EDITORS_INFO} title and + * {@link TibConstants#EDITORS_INFO_SPECS}. When theTibDialog
closes,
+ * it calls {@link #setEditor}.
+ *
+ */
+ public void getEditorInfo()
+ {
+ stopSplash();
+
+System.out.println("in getEditorINfo!");
+
+ if(editorsInitials != null) {
+ editorsDialog.setValue(1,editorsInitials);
+ }
+ if(editorsName != null) {
+ editorsDialog.setValue(0,editorsName);
+ }
+ editorsDialog.show();
+ }
+
+ /**
+ *
+ * This method is called when the {@link TibDialog} for getting editor information
+ * closes. The information is extracted from the TibDialog
and
+ * the variables {@link #editorsName} and {@link #editorsInitials} are set.
+ *
+ * This sets the {@link #todaysDate} variable to the current date in the form: + * YYYY-MM-DD. + *
+ */ + public void setDate() + { + Calendar cal = new GregorianCalendar(); + int year, month, day; + year = cal.get(Calendar.YEAR); + month = cal.get(Calendar.MONTH)+1; + day = cal.get(Calendar.DAY_OF_MONTH); + + todaysDate = year + DATE_DELIM + (month<10?"0":"") + month + DATE_DELIM + + (day<10?"0":"") + day; + } + + /** + *+ * This method returns the value of the today's date variable. + *
+ * + * @return String the present day's date in the form yyyy-mm-dd + */ + public String getDate() + { + return todaysDate; + } + + /** + *+ * Writes the preference data. This is read in and stored upon initialization of TiblEdit, when the + * program is restarted. + *
+ */ + public void exit() + { + //System.out.print("Exiting ..."); + if(currentFile != null) {closeFile();} + String outFile = DEFAULT_DIRECTORY + BIN + PREFS; + File prefsFile = new File(outFile); + try + { + PrintWriter out1 = + new PrintWriter( + new BufferedWriter( + new FileWriter(prefsFile))); + out1.println(EDITORS_NAME+PREFS_DELIM+editorsName); + out1.println(EDITORS_INITIALS+PREFS_DELIM+editorsInitials); + for(Iterator it = recent.iterator(); it.hasNext();) + { + File recentFile = (File)it.next(); + if(recentFile != null) { + out1.println(RECENT+PREFS_DELIM+recentFile.getPath()); + } + } + out1.close(); + } + + catch(IOException ioe) + { + System.out.println("An I/O Exception occurred in writing the prefs file."); + System.out.println("Message: " + ioe.getMessage()); + ioe.printStackTrace(); + } + + getFrame().dispose(); + System.exit(0); + } + // Accessors + /** + *+ * Sets the current directory to the given path. + *
+ * + * @param AFile
object that represents the path of the current directory.
+ */
+ public void setCurrentDirectory(File cd)
+ {
+ currentDirectory = cd;
+ }
+
+ /**
+ * + * Returns the path for the current working directory. + *
+ * + * @returnFile
- The current working directory as a File object.
+ */
+ public File getCurrentDirectory()
+ {
+ return currentDirectory;
+ }
+
+ /**
+ * + * Returns the file that is currently being worked on. + *
+ * + * @returnFile
- The currently open File object.
+ */
+ public File getCurrentFile()
+ {
+ return currentFile;
+ }
+
+ /**
+ * + * This sets the current display mode of the program. The values are: + *
+ * This returns the current display mode for the program. + *
+ * + * @return int - the current display mode + * + * @see setMode + */ + public int getMode() + { + return mode; + } + + /** + *+ * Returns the view or {@link TibFrame} that is the GUI of this program. + *
+ * + * @returnTibFrame
- The frame which displays the text information.
+ */
+ public TibFrame getFrame()
+ {
+ return tibFrame;
+ }
+
+ /**
+ * + * This returns the {@link TibDoc} presently being worked on. + *
+ * + * @return TheTibDoc
that is open.
+ */
+ public TibDoc getTibDoc()
+ {
+ return tibbibl;
+ }
+
+ /**
+ * + * Sets the {@link #selected_element} variable to the presently selected element. + *
+ * + * @param org.jdom.Element - the selected element. + */ + public void setSelectedElement(org.jdom.Element e) + { + selected_element = e; + } + + /** + *+ * Returns the presently selected element. + *
+ * + * @return org.jdom.Element - the selected element. + */ + public org.jdom.Element getSelectedElement() + { + return selected_element; + } + + /** + *+ * Returns the editors initials. + *
+ * + * @return String - the initials. + */ + public String getEditorsInitials() + { + return editorsInitials; + } + + /** + *+ * Returns the editors name + *
+ * + * @return String - the editor's name. + */ + public String getEditorsName() + { + return editorsName; + } + + /** + *+ * Recturns the vector containing the recent files opened. + *
+ * + * @return Vector the list of recent files + */ + public Vector getRecent() + { + return recent; + } + + /** + *
+ * This sets the {@link #fc} variable to a JFileChooser
and modifies
+ * it by adding an {@link XMLFilter} and a {@link TTFileView}. The latter serves
+ * to change the getName
function in the file chooser so that it
+ * displays the Tibbibl's text name rather than the actual file name. The file name
+ * is still used when the text is saved.
+ *
+ * This method sets the name of the file to be saved for a certain Tibbibl. It is invoked + * when the Master ID is set so that the name of the file reflects the master ID. + *
+ * + * @param String - the Master ID string that serves as the base of the file name + * + * + */ + public void setFileName(String masterID) + { + if(currentFile == null || masterID == null || masterID.trim().equals("")) {return;} + removeFromRecent(currentFile); + String currentFileName = currentFile.getName(); + File presDirectory = currentFile.getParentFile(); + + StringTokenizer toker = new StringTokenizer(tibbibl.getNormalizedTitle()," "); + String suffix = new String(); + for(int n=0;n<3;n++) { + if(toker.hasMoreTokens()) {suffix += "_" + toker.nextToken();} + } + + String masterName = masterID + suffix; + tibbibl.setID(masterName); + + if(presDirectory.equals(outDirectory)) { + File newFile = getNewFile(outDirectory, masterName); + System.out.println("Current file deleted in 1: " + currentFile.delete()); + tibbibl.setSysid(newFile.getName()); + save(newFile); + doMessage(RENAMING_FILE_SPECS, newFile.getName()); + } else { + File newFile = getNewFile(outDirectory, masterName); + System.out.println("Current file deleted in 2: " + currentFile.delete()); + tibbibl.setSysid(newFile.getName()); + save(newFile); + doMessage(SAVED_FILE_SPECS, newFile.getName()); + } + + } + +/** +*+* This method returns the new File created from renaming a file according to its master doxographical +* classification. It is called once an entry has been made through the {@link DoxWindow} and the ID and +* Sysid have been changed. It takes the folder that new files are written to and the master ID name and +* returns the new file. It first checks to make sure the name is unique since it is build from the doxographical +* classification number and the first 3 words of the title. If there is a conflict, it begins to add numbers to +* the end of the name until a unique name is arrived at. +*
+* +* @param File outDirectory - this is the directory to which processed files are written. +* +* @param String masterName - the is the master name for the file, e.g. Ng3.1.5.gsang_ba_'dus +* +* @return File - the uniquely named file created by combining the two above and checking for conflicts. +*/ + public File getNewFile(File outDirectory, String masterName) + { + File renamedFile = new File(outDirectory, masterName + ".xml"); + int n = 2; + if(renamedFile.exists()) { + /*int response = doConfirm(FILE_EXISTS_SPECS,renamedFile.getName()); + if(response == JOptionPane.YES_OPTION) {return renamedFile;}*/ + masterName += "_" + n; + renamedFile = new File(outDirectory, masterName + ".xml"); + } + while(renamedFile.exists()) { + /*int response = doConfirm(FILE_EXISTS_SPECS,renamedFile.getName()); + if(response == JOptionPane.YES_OPTION) {return renamedFile;}*/ + n++; + masterName = masterName.substring(0,masterName.length()-2) + n; + renamedFile = new File(outDirectory, masterName + ".xml"); + if(n==25) { break;} + } + if(renamedFile.exists()) {System.out.println("Warning checkFile has returned a file name that already exists!");} + System.out.println("File name from check file: " + renamedFile.getName()); + return renamedFile; + } + + // Helper methods + + + /** + *+ * This method uses a JFileChooser to get the user to choose a file and then + * calls {@link #openFile(File)} to open the selected file. + *
+ * + */ + public void openFile() + { + stopSplash(); + setFileChooser(); + + int returnVal = fc.showOpenDialog(getFrame()); + if(returnVal == JFileChooser.APPROVE_OPTION) + { + openFile(fc.getSelectedFile()); + } + } + + /** + *
+ * With the File
sent to it, this method uses
+ * an instance of an {@link XMLReader} to read the file. It sets the tibbibl
+ * variable to the TibDoc extracted by the reader. It then creates a {@link TextPane}, and
+ * sends it to the internal method {@link #showTitles}, which displays titles from the TibDoc
+ * in the TextPane. The text pane is then put in a JScrollPane
and this is sent
+ * to the {@link TibFrame} using its {@link TibFrame#fileOpened} method.
+ *
File
the file to be opened, sent by the file chooser.
+ */
+
+ public void openFile(File file)
+ {
+ stopSplash();
+ if(xreader.setDoc(file))
+ {
+ System.out.println("Opening file: " + file.getName());
+ currentFile = file;
+ tibFrame.fileOpened();
+ tibbibl = xreader.getDoc();
+ tibbibl.addEditor(editorsInitials, editorsName,todaysDate);
+ String temp = tibbibl.getNormalizedTitle();
+ if(temp.length()>100) {
+ int ind = temp.indexOf(' ',100);
+ if(ind < 50) { ind = 100;}
+ temp = temp.substring(0,ind) + " ...";
+ }
+ elemList = tibFrame.showTitles(tibbibl.getTitleFactory());
+ hasBeenSaved = false;
+ tibFrame.getTextPane().setCaretPosition(0);
+ addToRecent(file);
+
+ } else {
+ doMessage(OPEN_ERROR);
+ removeFromRecent(file);
+ }
+ }
+
+ /**
+ * + * This method takes a file and checks the recent file list to see if it is not already there. + * If it is not, then it adds it to the list. + *
+ * + * @param File - the file to be added to the recent list. + * + */ + public void addToRecent(File newFile) + { + String nfName = newFile.getName(); + int listIndex = -1; + for(Iterator it=recent.iterator();it.hasNext();) + { + File listFile = (File)it.next(); + if(listFile.equals(newFile) || listFile.getName().equals(nfName)) { + listIndex = recent.indexOf(listFile); + break; + } + } + if(listIndex == -1) { + recent.add(newFile); + if(recent.size()>RECENT_FILE_SIZE) {recent.remove(0);} + } else { + if(recent.remove(recent.get(listIndex))) {recent.add(0,newFile);} + } + + } + + /** + * This method removes a file from the recent list if the controller (TiblEdit) + * cannot open it. + */ + public void removeFromRecent(File badFile) + { + int index = recent.indexOf(badFile); + if(index > -1) {recent.remove(index); tibFrame.setRecentFiles(recent);} + } + + /** + *+ * Checks to make sure the file has first been saved. If not, then it prompts to save. + * If it has then, it calls {@link TibFrame#fileClosed} and sets {@link #currentFile} to null. + *
+ */ + public void closeFile() + { + if(!hasBeenSaved) { + int response = doConfirm(SAVE_SPECS); + if(response == JOptionPane.YES_OPTION) { + if(!saveTibbibl()) {return;} + } else if(response == JOptionPane.CANCEL_OPTION) { + return; + } + } + tibFrame.fileClosed(); + currentFile = null; + } + + /** + *+ * This method saves the edited {@link TibDoc} which is {@link #tibbibl} as a new + * document to the {@link TibConstants#OUT_DIRECTORY}, checking first to make sure + * it does not already exist. If it does, it prompts to overwrite. + *
+ */ + protected boolean saveTibbibl() + { + if(tibbibl == null) {return false;} + String outPath = DEFAULT_DIRECTORY + OUT_DIRECTORY; + if(currentFile != null) + { + outPath += currentFile.getName(); + } else { + outPath += "Ng.undef" + (outCount++) + ".xml"; + } + + File outFile = new File(outPath); + /*if(outFile.exists()) + { + String mess = "A file by the name of " + outFile.getName() + " already exists!\n" + + "Do you wish to write over it?"; + String messTitle = "File Exists! Overwrite?"; + int response = JOptionPane.showConfirmDialog(getFrame(), mess, messTitle, + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE); + if(response == JOptionPane.NO_OPTION) { + return saveAs(outFile); + } + }*/ + save(outFile); + return true; + } + + /** + *+ * This method actually writes the given file to disk. It is called from the {@link #saveTibbibl} method and + * from the {@link #saveAs} method. + *
+ * + * @param File - the file to be saved + */ + public void save(File outFile) + { + try + { + FileOutputStream fos = new FileOutputStream(outFile); + DataOutputStream dos = new DataOutputStream(fos); + XMLOut.output(tibbibl,fos); + hasBeenSaved = true; + currentFile = outFile; + dos.close(); + fos.close(); + System.out.println("File, " + outFile.getName() + ", saved!"); + addToRecent(outFile); + } + catch (IOException ioe) + { + String mess = "An IO Exception occurred, while trying to save file (" + + outFile.getAbsolutePath() + "). File did not write! "; + String emess = ioe.getMessage(); + if(emess != null & emess.length()>1) {mess += emess;} + System.out.println("Error: " + ioe.toString()); + System.out.println(mess); + ioe.printStackTrace(); + return; + } + } + + + /** + *+ * This method displays a Save As window through a JFileChooser. It is invoked from {@link #saveTibbibl} when + * the user attempts to save a file that exists but choses not to write over it. If the save option is chosen, + * it then calls {@link #saveTibbibl} which returns the success, creating a loop until either a unique file name is given, + * the overwrite option is chosen, or it is cancelled. + *
+ * + * @param File - the file + * + * @return boolean - whether the save operation was successful. + */ + public boolean saveAs(File outFile) + { + try + { + fc.setCurrentDirectory(outFile); + int response = fc.showSaveDialog(tibFrame); + if(response == JFileChooser.APPROVE_OPTION) + { + currentFile = fc.getSelectedFile(); + return saveTibbibl(); + } + } catch (HeadlessException he) {return false;} + return false; + + } + + /** + *+ * This method causes the {@link TibFrame} to display a table with the + * information on variant readings at the bottom of its text pane. It is + * invoked by double clicking on section of the {@link TextPane} that displays + * in yellow background, indicating there is an app element there. The clicking + * sets the selected element to that app element. If the area is not associated with + * an app, nothing happens. If it is, this method first locates the associated + * pagination and then calls the {@link TibFrame#showTable} method that takes + * a {@link TibTable}. The TibTable is constructed using the selected element or app, + * the {@link IDFactory} of the Tibbibl, and the pagination element. + *
+ */ + public void showApp() + { + if(selected_element == null) { + // return if there is no selected element + return; + } + + // find the associated pagination element + org.jdom.Element page = null; + parent = selected_element.getParent().getParent().getParent(); + if(parent.getName().equals(TDIV)) { + page = parent.getChild(PAGIN); + } else if(parent.getName().equals(TIBBIBL)) { + page = parent.getChild(PHYSDEC).getChild(PAGIN); + } + // if the pagination is found + if(page != null) { + // If it's a new app call the appropriate method to insert the yellow backgroun + if(mode == NEW_AP) {tibFrame.displayNewApp();} + // + tibFrame.showTable(new TibTable(selected_element,tibbibl.getIDFactory(),page)); + } + } + + public void insertNewEdition() + { + if(tibbibl != null) + { + + TibDialog tdialog = new TibDialog(this,NEW_ED_INFO,NEW_ED_INFO_SPECS); + tdialog.showDialog(); + } + } + + public void submitNewEditionInfo(TibDialog tdia) + { + IDFactory idf = tibbibl.getIDFactory(); + String sigla = tdia.getValue(ED_SIG); + if(idf.hasEdition(sigla)) { + int response = doConfirm(ED_EXISTS_SPECS); + if(response == JOptionPane.YES_OPTION) + { + idf.removeEd(sigla); + } + } + idf.addEditionConsulted(tdia.getResults()); + idf.addSourceConsulted(sigla,editorsInitials,editorsName); + } + + /** + *+ * This method inserts a title to be critically edited that is based on a particular + * edition title. It is called when an edition title is double clicked or when + * the corresponding insert command is chosen from the menu. It first locates the + * element at the caret, makes sure it is a title and then calls {@link #enterTranslation}. + * (Should it check for the title's type here?) + *
+ */ + public void insertCritTitle() + { + if(elemList == null) {return;} + element = elemList.getElementAt(tibFrame.getCaretPosition()); + if(element != null && element.getName().equals(TITLE)) { + selected_element = element; + enterTranslation(); + } + } + + /** + *
+ * This method is for inserting a new edition title. Edition titles cannot be
+ * critically edited. They represent titles as they appear in particular editions.
+ * One choses a particular edition title as the basis for a critical title which
+ * then can have app elements collating the various readings. This method uses
+ * a {@link TibDialog} with {@link TibConstants@NEW_ED_TITLE_INFO} and
+ * {@link TibConstants#NEW_ED_TITLE_INFO_SPECS} to get the title and its pagination.
+ * When the TibDialog
is submitted, the {@link #insertNewEdTitle} method
+ * is called with that TibDialog
.
+ *
+ * This is called when a {@link TibDialog} is submitted with new edition title information.
+ * It checks to see if the sigla of the new title (i.e., the edition it is from) already
+ * exists in the texts TibidDecl, using the tibbibl's {@link IDFactory}. If it does not,
+ * exist, another {@link TibDialog} is called with {@link TibConstants#NEW_ED_INFO} and
+ * {@link TibConstants#NEW_ED_INFO_SPECS} to get all the relevant information. When that
+ * second TibDialog
is closed, the {@link #insertNewEdAndTitle} method
+ * is invoked. Otherwise, if the edition is known, it calls {@link TibFrame#showTitles}
+ * with an {@link TitleFactory} and a {@link #mode} equal to {@link TibConstants#NEW_TITLE}
+ * to display a place to enter the new title.
+ *
+ * This enters the information from the {@link TibDialog} called by {@link #insertNewEdTitle} + * into the TibidDecl of the Tibbibl and then calls {@link TibFrame#showTitles} with + * the {@link TitleFactory} of the Tibbibl and a {@link #mode} set to {@link TibConstants#NEW_TITLE}. + * This displays an entry place for the new title in the {@link TextPane}. + *
+ * + * @param TibDialog - the TibDialog with the information concerning the new edition. + */ + public void insertNewEdAndTitle(TibDialog tdia) + { + IDFactory idf = tibbibl.getIDFactory(); + idf.addEditionConsulted(tdia.getResults()); + idf.addSourceConsulted(tdia.getValue(ED_SIG),editorsInitials,editorsName); + tdia.dispose(); + setSelectedElement(tibbibl.addTitle(selected_element,tdia.getValue(ED_SIG),tdia.getValue(TITLE_PAGE))); + mode = NEW_TITLE; + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + setCaretPosition(); + } + + /** + *+ * This method is called when one either double clicks on a title or chooses enter a translation + * from the menu. It first determines if the selected element is the normalized title, in which case + * it sets the {@link #mode} to {@link TibConstants.ENTER_NORMALIZED ENTER_NORMALIZED} and redisplays with the appropriate prompts. + * Otherwise, it makes sure there is a Tibetan title there and not "No title given" or "Not specified" and + * if it's a valid title, asks the user if they want to create a critical title with the selected title + * as its base. If so, it redisplays with the appropriate prompts. + * + *
+ */ + + public void enterTranslation() { + if(selected_element.getName().equals(TITLE)) { + String type = selected_element.getAttributeValue(TYPE); + if(type != null && type.indexOf("Normalized")>-1) { + mode = ENTER_NORMALIZED; + } else { + parent = selected_element.getParent(); + child = parent.getChild(TITLE); + if(child != null) { + // If there are a list of Title elements in this titleDecl, the first + // one will always be the critical edition of the title with corresp=Ng + // if it is not there, then it needs to be added. + String corresp = child.getAttributeValue(CORRESP); + if(corresp != null && corresp.equals(NG)) { + selected_element = child; + } else { + if(corresp == null) { + System.out.println("No corresp element: \n" + outputString(child)); + } + + String text = selected_element.getText(); + if(text.indexOf(NOT_SPEC)>-1) { + doMessage(NOT_SPEC_SPECS); + mode = CANC; + tibFrame.getTextPane().addCaretListener(tibFrame); + return; + } + if(text.indexOf(NO_TITLE)>-1) { + doMessage(NO_TITLE_SPECS); + mode = CANC; + tibFrame.getTextPane().addCaretListener(tibFrame); + return; + } + + String mess = "Do you wish to create a critical edition for this title, \n" + + "using the following title as the base: \n"; + String title = TibDoc.cleanString(selected_element.getText()); + if(title.length()>50) { + int half = title.length()/2; + int index = title.indexOf(" ",half); + if(index == -1) {mess += title;} else { + mess += title.substring(0,index) + "\n" + title.substring(index+1); + } + } else { + mess += title; + } + mess += "\nEdition: " + selected_element.getAttributeValue(CORRESP); + String[] specs = {mess,"Create Critical Title", + Integer.toString(JOptionPane.YES_NO_OPTION)}; + int resp = doConfirm(specs); + if(resp == JOptionPane.YES_OPTION) { + mode = ENTER_TRANS; + selected_element = tibbibl.createCriticalTitle(selected_element,editorsInitials); + } + } + } + } + + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + //setCaretPosition(); + } + } + + + /** + *
+ * This method is called when a new translation has been entered into the
+ * {@link TextPane} and Enter has been pressed. It locates the text of the new
+ * translation in the TextPane from the {@link TibConstants#ENTER_TRANS_PHRASE}
+ * prompt to the next paragraph mark "/n", and then calls the {@link TibDoc#addTranslation}
+ * method with this translation String
and the {@link #selected_element}.
+ * The display mode ({@link #mode}) is then set to {@link TibConstants#NORM} and
+ * the text is redisplayed using {@link TibFrame@showTitles} which returns
+ * an {@link ElementList} that is assigned to {@link #elemList}.
+ *
+ * This method is called when inserting an Edition title within a title decl. This is a title + * that belongs to a particular edition and is to be used as a source for a critical title. + * The infromation is received from a {@link TibDialog} and then a prompt for the title in the + * textpane, which is then read and placed in the title element. + *
+ */ + private void insertNewTitleAndTranslation() + { + + String title_text, trans, full_text; + tp = tibFrame.getTextPane(); + full_text = tp.getText(); + trans = new String(); + try { + int enterPhraseindex = full_text.indexOf(ENTER_TITLE_PHRASE); + if(enterPhraseindex == -1) { + enterPhraseindex = full_text.indexOf(ENTER_TITLE_PHRASE.substring(0,ENTER_TITLE_PHRASE.length()-2)); + } + if(enterPhraseindex>-1) { + + title_text = full_text.substring(enterPhraseindex+ENTER_TITLE_PHRASE.length()-2); + title_text = title_text.substring(0,title_text.indexOf("\n")); + if(title_text.substring(0,1).equals(":")) {title_text = title_text.substring(1);} + if(title_text != null) { + selected_element.setText(title_text.trim()); + } + } + + } catch (IndexOutOfBoundsException ibe) + { + System.out.println("Index out of bounds setting translation:\n" + trans + "\n" + + ibe.getMessage()); + ibe.printStackTrace(); + } + + mode = NORM; + selected_element = null; + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + //setCaretPosition(); + } + +/** +*+* This method updates the information for the normalized title after it has been entered into +* the {@link TextPane} by the editor and Enter has been pressed. It replaces the text within +* the Title tag for the Tibetan and its child Foreign tag for the english translation. It then +* calls {@link TibDoc#updateTextHeader() the updateTextHeader} method in {@link TibDoc} and +* redisplays. +*
+*/ + private void updateNormalizedTitle() + { + String title_text, trans, full_text; + tp = tibFrame.getTextPane(); + full_text = tp.getText(); + trans = new String(); + try { + title_text = full_text.substring(full_text.indexOf(ENTER_NORMALIZED_PHRASE)); + title_text = title_text.substring(ENTER_NORMALIZED_PHRASE.length()); + title_text = title_text.substring(0,title_text.indexOf("\n")); + if(title_text.substring(0,1).equals(":")) {title_text = title_text.substring(1);} + if(title_text != null) { + selected_element.setText(title_text.trim()); + } + org.jdom.Element foreign = selected_element.getChild(FOREIGN); + if(foreign == null) { + foreign = new org.jdom.Element(FOREIGN); + foreign.setAttribute(LANG,ENG); + selected_element.addContent(foreign); + } + trans = full_text.substring(full_text.indexOf(ENTER_NORM_TRANS_PHRASE)); + trans = trans.substring(ENTER_NORM_TRANS_PHRASE.length()); + trans = trans.substring(0,trans.indexOf("\n")); + if(trans.substring(0,1).equals(":")) {trans = trans.substring(1);} + if(trans != null) { + foreign.setText(trans.trim()); + } + + + } catch (IndexOutOfBoundsException ibe) + { + System.out.println("Index out of bounds setting translation:\n" + trans + "\n" + + ibe.getMessage()); + ibe.printStackTrace(); + } + + mode = NORM; + selected_element = null; + tibbibl.updateTextHeader(); + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + //setCaretPosition(); + + } + + /** + *+ * This method is called when a selection of title text is made and the insert + * variant reading choice is taken from the Insert menu. It first checks to make + * sure the caret is in the appropriate place using {@link #checkCaretPosition} with + * the param {@link TibConstants#AP}. If it is a viable insertion point, it calculates + * the offset of the selection from the previous paragraph mark and calls + * {@link TibDoc#insertApp} using the {@link #selected_element}, the selected text, + * and this offset from the last paragraph integer. The {@link #mode} is then set + * to {@link TibConstants#NEW_AP} and the {@link #showApp} method is called. + *
+ */ + public void insertApp() + { + if(checkCaretPosition(AP)) { + if(selected_element == null) { + System.out.println("Selected element is null in insertApp!"); + return; + } + TextPane tp = tibFrame.getTextPane(); + String docText = ""; + try { + docText = tp.getDocument().getText(0,tp.getDocument().getLength()); + } catch (BadLocationException ble) { + docText = tp.getText(); + System.out.println("Can't get documents text!"); + } + String selText = tibFrame.getTextPane().getSelectedText(); + if(selText == null || selText.length()==0) { + System.out.println("Nothing selected!"); + doMessage(NO_SELECTION_SPECS); + } else { + + int selStart = tp.getSelectionStart(); + int prevPara = docText.lastIndexOf("\n",selStart); // had a +1 + int postPara = docText.indexOf("\n",selStart); + int offset = selStart - prevPara; + selected_element = tibbibl.insertApp(selected_element,selText,offset); + setMode(NEW_AP); + tibFrame.hideEditions(); + showApp(); + } + } + } + + /** + *+ * This method inserts a particular type of discussion depending on the setting of the + * type parameter. When type equals {@link TibConstants.TITLE TITLE}, a discussion will be inserted + * for the title at the cursor position of the {@link TextPane}. When type equals {@link TibConstants.GEN GEN} + * the user will be prompted with a list of options to choose from. + *
+ * + * @param type - the string indicating which typeof discussion to insert. + */ + public void insertDiscussion() + { + DiscDialog discDia = tibFrame.getDiscussionDialog(tibbibl); + discDia.showDiscussionDialog(); + } + + /** + * This method takes a TitleDecl or any grouping element that might contain a discussion element and + * checks to see if it has a prose discussion within it. If so, this prose discussion element (i.e., + * one that has type=brief or type=full) is returned. Otherwise, null is return. It is used also by {@link DiscDialog} + * and so needs to be static. + */ + + public static org.jdom.Element locateDisc(org.jdom.Element parent) + { + org.jdom.Element outDisc = null; + List discEls = parent.getChildren(DISC); + for(Iterator it = discEls.iterator(); it.hasNext();) { + outDisc = (org.jdom.Element)it.next(); + String discType = outDisc.getAttributeValue(TYPE); + if(discType.equalsIgnoreCase(BRIEF) || discType.equalsIgnoreCase(FULL)) { + return outDisc; + } + } + return null; + } + + /** + *+ * This method is used to display a text's variant titles. It first calls + * {@link TibFrame#hideEditions} to hide any table displaying at the bottom. + * It then sets the mode to {@link TibConstants#NORM} and calls {@link TibFrame#showTitles} + *
+ */ + public void showTitles() + { + tibFrame.hideEditions(); + if(tibbibl == null) {return;} + if(mode == CANCEL_NEW_APP) { + tibbibl.removeApp(selected_element); + } + mode = NORM; + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + //setCaretPosition(); + } + + /** + *+ * This method is called from the {@link TibTable} which is observed by this + * controller. When it is submitted, it notifies this observer and this method is run. + * It takes a hashtable of arguments, as follows: + *
+ * This method is invoked from the Edit menu and allows the user to edit an already + * existing translation for a title by inserting the Enter translation prompt prior to + * the text of the translation and allowing the {@link TextPane} to be editable. + *
+ */ + public void editTranslation() + { + if(checkCaretPosition(TRANS_EDIT)) + { + int caretPos = tibFrame.getTextPane().getCaretPosition(); + mode = DO_TRANS; + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + //tibFrame.getTextPane().setCaretPosition(caretPos); + } else { + doMessage(INVALID_TRANS_SPECS); + } + } + + /** + *+ * This method is invoked after a translation has been edited and the Enter key + * has been pressed. It replaces the text of the Foreign element containing the + * translation with the next text between the Enter translation prompt and the + * subsequent paragraph return. + *
+ * + * @see #keyPressed - the implementation of the KeyListener that invokes this method. + */ + public void updateTranslation() + { + String trans, full_text; + org.jdom.Element foreign; + if(selected_element == null) {return;} + tp = tibFrame.getTextPane(); + full_text = tp.getText(); + trans = new String(); + try { + if(selected_element.getName().equals(TITLE)) { + foreign = selected_element.getChild(FOREIGN); + } else if(selected_element.getName().equals(FOREIGN)) { + foreign = selected_element; + } else { + return; + } + + trans = full_text.substring(full_text.indexOf(ENTER_TRANS_PHRASE)); + trans = trans.substring(ENTER_TRANS_PHRASE.length()); + trans = trans.substring(0,trans.indexOf("\n")); + if(trans.substring(0,1).equals(":")) {trans = trans.substring(1);} + if(trans != null) { + foreign.setText(trans.trim()); + } + + + } catch (IndexOutOfBoundsException ibe) + { + System.out.println("Index out of bounds setting translation:\n" + trans + "\n" + + ibe.getMessage()); + ibe.printStackTrace(); + } + + mode = NORM; + selected_element = null; + elemList = tibFrame.showTitles(tibbibl.getTitleFactory()); + + } + + public void removeApp() + { + int pos = getFrame().getTextPane().getCaretPosition(); + element = elemList.getElementAt(pos); + if(element != null && element.getName().equals(AP)) + { + int response = doConfirm(REMOVE_APP_SPECS); + if(response == JOptionPane.YES_OPTION) { + tibbibl.removeApp(element); + } + showTitles(); + } + getFrame().getTextPane().setCaretPosition(pos); + } + + public void removeTitle() + { + int pos = getFrame().getTextPane().getCaretPosition(); + element = elemList.getElementAt(pos); + parent = element.getParent(); + if(element != null && element.getName().equals(TITLE)) + { + String corspVal = element.getAttributeValue(CORRESP); + org.jdom.Element sourceListing = tibbibl.findElement(NAME,ID,corspVal); + String srcCorrVal = (sourceListing==null?null:sourceListing.getAttributeValue(CORRESP)); + if((corspVal != null && corspVal.equals(editorsInitials)) || + (srcCorrVal != null && srcCorrVal.equals(editorsInitials))) { + int response = doConfirm(REMOVE_ED_TITLE_SPECS); + if(response == JOptionPane.YES_OPTION) { + element.detach(); + removePageRefs(parent,corspVal); + showTitles(); + } + } else { + doMessage(REMOVE_ED_TITLE_ERROR); + } + } + getFrame().getTextPane().setCaretPosition(pos); + } + + public void removePageRefs(org.jdom.Element parentEl, String corrsp) + { + if(parentEl.getChild(SRC) != null) { + org.jdom.Element src = parentEl.getChild(SRC); + int childIndex = -1; + for(Iterator it=src.getChildren(NUM).iterator();it.hasNext();) { + child = (org.jdom.Element) it.next(); + String crsAtt = child.getAttributeValue(CORRESP); + if(corrsp.equals(crsAtt)) { childIndex = src.getChildren().indexOf(child); break; } + } + if(childIndex > -1) { child.detach(); childIndex = -1;} + grandparent = parent.getParent(); + if(grandparent.getChild(PHYSDEC) != null) { + grandparent = grandparent.getChild(PHYSDEC); + parent = grandparent.getChild(PAGIN); + for(Iterator it=parent.getChildren(NUM).iterator();it.hasNext();) { + child = (org.jdom.Element) it.next(); + String crsAtt = child.getAttributeValue(CORRESP); + if(corrsp.equals(crsAtt)) { childIndex = parent.getChildren().indexOf(child); break; } + } + } + if(childIndex > -1) { child.detach(); childIndex = -1;} + } else { + grandparent = parentEl.getParent(); + int childIndex = -1; + if(grandparent.getChild(PAGIN) != null) { + parent = grandparent.getChild(PAGIN); + for(Iterator it=parent.getChildren(NUM).iterator();it.hasNext();) { + child = (org.jdom.Element) it.next(); + String crsAtt = child.getAttributeValue(CORRESP); + if(corrsp.equals(crsAtt)) { childIndex = parent.getChildren().indexOf(child); break; } + } + if(childIndex > -1) { child.detach(); childIndex = -1;} + } + } + } + + public void deleteEdition(org.jdom.Element edToDie) + { + if(getTibDoc() == null || edToDie == null) { return; } + String corrsp = edToDie.getAttributeValue(CORRESP); + org.jdom.Element edNameEl = tibbibl.findElement(NAME,ID,corrsp); + boolean failure = false; + String mess = new String(); + if(edNameEl != null) + { + String edNameCor = edNameEl.getAttributeValue(CORRESP); + if(corrsp == null || edNameCor.equals(editorsInitials)) { + edToDie.detach(); + edNameEl.detach(); + org.jdom.Element physdecl = tibbibl.findElement(PHYSDEC); + org.jdom.Element numFound = null; + for(Iterator it = physdecl.getChild(PAGIN).getChildren(NUM).iterator();it.hasNext();) { + org.jdom.Element num = (org.jdom.Element)it.next(); + String numCorr = num.getAttributeValue(CORRESP); + if(numCorr != null && numCorr.equals(corrsp)) { + numFound = num; + break; + } + } + if(numFound != null) { + numFound.detach(); + System.out.println("Detaching num in physdecl\n" + outputString(physdecl)); + } + org.jdom.Element[] others = tibbibl.findElements(CORRESP,corrsp); + for(int n=0; n
+ * This is a generic method to display a {@link javax.swing.JOptionPane} message
+ * dialog it takes a String
array with three specs.
+ *
JOptionPane
.
+ *
+ * This is a generic method to display a {@link javax.swing.JOptionPane} confirm
+ * dialog it takes a String
array with three specs.
+ *
JOptionPane
.
+ * +* This method sets the caret position to just after the enter information prompt +* depending on the {@link #mode} at the time it is called. The mode gives an indication +* which prompt is being used and should be searched for to determine the corresponding index +* at which to set the caret. This is not working correctly. 11 needs to be added to the index +* for it to come out even approximately correct. Why is this? +*
+*/ + public void setCaretPosition() + { + String searchString = null; + if(mode == NORM) { + return; + } else if(mode == ENTER_TRANS || mode == DO_TRANS) { + searchString = ENTER_TRANS_PHRASE; + } else if(mode == ENTER_NORMALIZED) { + searchString = ENTER_NORMALIZED_PHRASE; + } else if(mode == NEW_TITLE) { + searchString = ENTER_TITLE_PHRASE; + } + if(searchString == null) { System.out.println("Null mode in set Caret Position of TiblEdit!"); return;} + + TextPane tp = tibFrame.getTextPane(); + String text = tp.getText(); + int index = text.indexOf(searchString); + if(index>0) { + tp.setCaretPosition(index); + } + } + + /** + *+ * This method checks the position of the caret to see if it is an appropriate + * place to perform certain actions depending on the Type parameter supplied. + * The types available are: + *
+ * This is a static method to display a {@link javax.swing.JOptionPane} input
+ * dialog it takes a String
array with three specs.
+ *
JOptionPane
.
+ * String
+ * that was inputed.
+ *
+ * @param String[] - the specifications for the input dialog
+ *
+ * @return String - the string entered by the user.
+ *
+ */
+ public static String promptInput(String[] specs)
+ {
+ return JOptionPane.showInputDialog(null,specs[0],specs[1],Integer.parseInt(specs[2]));
+ }
+
+ /**
+ *
+ * A public static method that converts a Vector
into an array of Strings
.
+ *
Vector
The vector to be converted.
+ *
+ * @return String[]
The resulting array of Strings
.
+ */
+ public static String[] toStringArray(Vector v)
+ {
+ Object[] objs = v.toArray();
+ String[] out = new String[objs.length];
+ for(int n=0; nObject
array into an array of Strings
.
+ *
+ *
+ * @param Object[]
The object array to be converted.
+ *
+ * @return String[]
The resulting array of Strings
.
+ */
+ public static String[] toStringArray(Object[] objs)
+ {
+ String[] out = new String[objs.length];
+ for(int n=0; norg.jdom.Element
The element to be turned into a string.
+ *
+ * @return String
The resulting string version of the element.
+ */
+ public static String outputString(org.jdom.Element e)
+ {
+ if(e == null) {return "No element!\n";}
+ return xop.outputString(e);
+ }
+
+
+ // Constructor
+
+ /**
+ * + * The only constructor takes no arguments and simply calls the {@link #init} method. + *
+ */ + public TiblEdit() + { + init(); + + // this is for the number of the written out file when there is no currentFile defined + // If this is kept (which it probably won't be), it must be recorded upon the + // program closing and read it upon reopening. + outCount = 1; + } + + public static void showSplash() + { + IntroSign is = new IntroSign(); + t = new Thread(is,"intro"); + t.start(); + } + + /** + *+ * This static method stops the splash screen from displaying by interrupting + * the thread it is on {@link #t} and setting it to null. + *
+ */ + public static void stopSplash() + { + if(t != null) {t.interrupt();t=null;} + } + + public static void main(String[] args) + { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + System.err.println("Exception: " + e.getMessage() + "\n" + + e.getClass().getName()); + } + TiblEdit app = new TiblEdit(); + } + + // Listener Methods + + // MouseEvent listener + /** + *+ * This implementation of the mouse listener checks to make sure the source is + * the {@link TextPane}. Then, it makes sure the {@link #mode} is {@link TibConstants#NORM} + * to make sure action is viable. Thus, it only responds when the TextPane + * is click when nothing else is being inserted etc. It makes sure its a double click + * and there is an {@link ElementList} defined to check. It checks the {@link #elemList} + * for the selected element, if it is a {@link TibConstants#TITLE}, then it calls + * {@link #enterTranslation}. If it is an {@link TibConstants#AP}, then it calls + * {@link #showAp}. + *
+ * + * @param MouseEvent - the required parameter for this abstract method. + */ + public void mouseClicked(MouseEvent me) + { + if(t !=null) stopSplash(); + if(me.getSource() instanceof TextPane) + { + TextPane tp = (TextPane)me.getSource(); + int noc = me.getClickCount(); + int pos = tp.getCaretPosition(); + if(mode == NORM && elemList != null) { + if(noc>1 ) { + setSelectedElement(elemList.getElementAt(pos)); + if(selected_element != null) { + String name = selected_element.getName(); + if(name.equals(TITLE)) { + tp.removeCaretListener(tibFrame); + enterTranslation(); + } else if(name.equals(AP)) { + tp.removeCaretListener(tibFrame); + mode = SHOW_AP; + showApp(); + } + } else { + selected_element = null; + tibFrame.getTextPane().setCaretPosition(pos); + } + } else { + element = elemList.getElementAt(pos); + if(element.getName().equals(AP)) { + getFrame().removeAppItem.setEnabled(true); + } else { + getFrame().removeAppItem.setEnabled(false); + } + } + } else if(mode == CANC) { + mode = NORM; + tibFrame.getTextPane().setCaretPosition(pos); + } + + } + } + + public void mousePressed(MouseEvent me) {} + public void mouseReleased(MouseEvent me) {} + public void mouseEntered(MouseEvent me) {} + public void mouseExited(MouseEvent me) {} + + //Key Event Listner + /** + *+ * This implementation of the KeyListener interface is used when information + * is being added directly to the {@link TextPane} being displayed. If the + * Enter key is pressed, the it checks the {@link #mode}. If the mode is + * {@link TibConstants#ENTER_TRANS}, then it calls {@link insertTranslation}. + * If the mode is {@link NEW_TITLE}, it calls {@link insertNewTitleAndTranslation}. + *
+ * + * @param KeyEvent - the required parameter for this abstract method. + */ + public void keyPressed(KeyEvent ke) { + if(ke.getKeyCode() == KeyEvent.VK_ENTER) { + int pos = tibFrame.getTextPane().getCaretPosition(); + if(mode == ENTER_TRANS) { + insertTranslation(); + hasBeenSaved = false; + } else if(mode == NEW_TITLE) { + insertNewTitleAndTranslation(); + hasBeenSaved = false; + } else if(mode == ENTER_NORMALIZED) { + updateNormalizedTitle(); + hasBeenSaved = false; + } else if(mode == DO_TRANS) { + updateTranslation(); + hasBeenSaved = false; + } + setMode(NORM); + + tibFrame.getTextPane().setCaretPosition(pos); + } + } + public void keyReleased(KeyEvent ke) {} + public void keyTyped(KeyEvent ke) { + } + + // Observer for TibTable App entries + /** + *
+ * The implementation of the Observer
interface is used for listening
+ * to the {@link TibTable} that displays variant reading information. That table
+ * is displayed along with a button panel for submitting and canceling. When either
+ * of those buttons are pressed. The TibTable notifies its observers (the TiblEdit
+ * controller) with an argument of a Hashtable
with keyed specs.
+ * If the type key equals {@link TibConstants#APP_SUBMIT} then the {@link #doAppSubmission}
+ * is called with the arguments. If it is {@link TibConstants#CANCEL}, then
+ * it calls the {@link #showTitles} method with mode {@link TibConstants#CANCEL_NEW_APP}.
+ *
+ * This method cleans the title element of consequetive Text elements so + * that the {@link #isAppInsertable} method will not mistakenly think that + * an app cannot be inserted since it crosses a part boundary. The two consequetive + * jdom.org.Text elements will be combined and the second one removed. + *
+ */ + org.jdom.Text lastText, textElement; + Iterator it = title.getContent().iterator(); + Vector toRemove = new Vector(); + lastText = null; + while(it.hasNext()) + { + Object item = it.next(); + if(item instanceof org.jdom.Text) { + if(lastText == null) { + lastText = (org.jdom.Text)item; + } else { + String lastTextString = lastText.getText(); + textElement = (org.jdom.Text)item; + String thisTextString = textElement.getText(); + if(!lastTextString.endsWith(" ") && + !thisTextString.startsWith(" ")) + { + thisTextString += " "; + } + lastText.setText(lastTextString + thisTextString); + toRemove.add(item); + } + } else { + lastText = null; + } + } + for(it = toRemove.iterator(); it.hasNext();) + { + title.getContent().remove(it.next()); + } + } + + private void parse() + { + /** + *+ * This method parses the title by finding its constituent parts and creating + * a {@link TitleParser.TitlePart} out of them and adding each TitlePart to + * the vector {@link #parts}. The title parts contain the text for display, its + * beginning and end indexes, and the corresponding JDOM part, whether it be + * an element, text, or string. + *
+ */ + parts = new Vector(); + outText = new String(); + Iterator it = title.getContent().iterator(); + TitlePart prevPart = null; + + while(it.hasNext()) + { + boolean isApp = false; + item = it.next(); + String stringItem = new String(); + if(item instanceof org.jdom.Element) { + contentItem = (org.jdom.Element)item; + if(contentItem.getName().equals(AP)) { + stringItem = cleanString(contentItem.getChild(LM).getText()); + isApp = true; + } else if(contentItem.getName().equals(FOREIGN)) { + foreign = contentItem; + continue; + } else { + stringItem = cleanString(contentItem.getText()); + System.out.println("Found an inner element that's not ap or foreign: " + contentItem.toString()); + } + } else if(item instanceof org.jdom.Text) { + textItem = (org.jdom.Text)item; + stringItem = cleanString(textItem.getText()); + } else if(item instanceof String) { + stringItem = cleanString((String)item); + } else { + System.out.println("A kind of title content found that is not recognized!\n" + + item.toString()); + continue; + } + + if(!outText.endsWith(" ") && !stringItem.startsWith(" ")) { + if(isApp) { + TitlePart tpart = (TitlePart)parts.lastElement(); + tpart.addSpace(); + outText += " "; + } else { + stringItem = " " + stringItem; + } + } + int start = outText.length()+1; + outText += stringItem; + parts.add(new TitlePart(stringItem,start,item,isApp)); + prevPart = (TitlePart)parts.lastElement(); + } + + titleText = cleanString(outText); + } + + private void setStyles() + { + ElementStyle es; + styleElements = new Vector(); + + Iterator it = parts.iterator(); + while(it.hasNext()) + { + es = null; + TitlePart tpart = (TitlePart)it.next(); + String text = tpart.text; + if(tpart.isApp) { + org.jdom.Element e = (org.jdom.Element)tpart.associatedItem; + es = new ElementStyle(text,TextPane.VARIANT,e); + } else { + es = new ElementStyle(text,TextPane.REG,title); + } + styleElements.add(es); + } + if(styleElements.size()>0) { + try { + es = (ElementStyle)styleElements.firstElement(); + if(es.getText().equals(" ")) {styleElements.remove(es);} + es = (ElementStyle)styleElements.lastElement(); + if(es.getText().equals(" ")) {styleElements.remove(es);} + } catch (NoSuchElementException nsee) {} + } + } + + public void setTitle(org.jdom.Element ttl) + { + title = ttl; + parse(); + setStyles(); + } + + public org.jdom.Element getTitle() + { + return title; + } + + public String getTitleText() + { + return titleText; + } + + public org.jdom.Element getTranslation() + { + return foreign; + } + + public Vector getStyles() + { + if(styleElements.size()==0) { + styleElements.add(new ElementStyle("",TextPane.REG,title)); + } + return styleElements; + } + +/** +*+* This method checks the parts of the title to see if an app (or apparatus) element is insertable. The +* main thing it checks for is that the range of text does not span over an already existing app. +*
+* +* @param startInsert the insertion point within the display of the titles text relative to the beginning of the line. +* +* @param txt the selected text which is to be marked up with the app. This is necessary to make sure that +* the text does not fall completely within an already existing app. +* +* @return boolean - whether or not this is an acceptable place to insert an app element. +*/ + public boolean isAppInsertable(int startInsert, String txt) + { + + if(parts == null) {return false;} + Iterator it = parts.iterator(); + while(it.hasNext()) + { + TitlePart tpart = (TitlePart)it.next(); + + int tpStart = tpart.start; + int tpEnd = tpart.end; + if(startInsert>=tpStart && startInsert