/* Copyright (C) 2002-2003 Nizar N. Batada nbatada@stanford.edu All programs in this directory and subdirectories are published under the GNU General Public License as described below. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Further information about the GNU GPL is available at: http://www.gnu.org/copyleft/gpl.ja.html */ package net.sf.jabref; import net.sf.jabref.gui.FileDialogs; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.*; import java.util.Iterator; import javax.swing.*; class EntryCustomizationDialog extends JDialog implements ItemListener { BibtexEntryType type; JScrollPane reqSP, optSP; JButton ok, cancel, helpButton, delete, importTypes, exportTypes; JPanel panel=new JPanel(), fieldPanel = new JPanel(), typePanel = new JPanel(); int width=10; JLabel messageLabel=new JLabel("", SwingConstants.CENTER); JTextField name = new JTextField("", width); JTextArea req_ta=new JTextArea("",5,width),//10 row, 20 columns opt_ta=new JTextArea("",5,width);//10 row, 20 columns // need to get FIeld name from somewhere JComboBox types_cb = new JComboBox(); HelpAction help; GridBagLayout gbl = new GridBagLayout(); GridBagConstraints con = new GridBagConstraints(); JPanel buttonPanel = new JPanel(); JabRefFrame parent; EntryCustomizationDialog ths = this; public EntryCustomizationDialog(JabRefFrame parent) { //Type=Article, Book etc // templateName will be used to put on the dialog frame // create 10 default entries // return an array super(parent.getFrame(),Globals.lang("Customize entry types"), false); this.parent = parent; help = new HelpAction(parent.helpDiag, GUIGlobals.customEntriesHelp, "Help", GUIGlobals.getIconUrl("helpSmall")); setTypeSelection(); //setSize(440,400); initialize(); makeButtons(); reqSP = new JScrollPane(req_ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); optSP = new JScrollPane(opt_ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); //helpButton = new JButton(help); //helpButton.setText(null); JToolBar tlb = new JToolBar(); tlb.setFloatable(false); tlb.add(help); //panel.setBackground(GUIGlobals.lightGray); //buttonPanel.setBackground(GUIGlobals.lightGray); panel.setLayout(gbl); typePanel.setLayout(gbl); fieldPanel.setLayout(gbl); //panel.setBorder(BorderFactory.createEtchedBorder()); fieldPanel.setBorder(BorderFactory.createEtchedBorder()); typePanel.setBorder(BorderFactory.createEtchedBorder()); JLabel lab = new JLabel(Globals.lang("Type")+": "), lab2 = new JLabel(Globals.lang("Name")+": "); con.insets = new Insets(5, 5, 5, 5); gbl.setConstraints(lab, con); gbl.setConstraints(lab2, con); gbl.setConstraints(types_cb, con); con.weightx = 1; con.fill = GridBagConstraints.HORIZONTAL; gbl.setConstraints(name, con); con.fill = GridBagConstraints.NONE; con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 0; //gbl.setConstraints(helpButton, con); gbl.setConstraints(tlb, con); con.gridwidth = 1; typePanel.add(lab); typePanel.add(types_cb); typePanel.add(lab2); typePanel.add(name); //typePanel.add(helpButton); typePanel.add(tlb); lab = new JLabel(Globals.lang("Required fields")); con.fill = GridBagConstraints.BOTH; con.weightx = 1; gbl.setConstraints(lab, con); con.weighty = 1; gbl.setConstraints(reqSP, con); fieldPanel.add(lab); con.gridwidth = GridBagConstraints.REMAINDER; lab = new JLabel(Globals.lang("Optional fields")); con.weighty = 0; gbl.setConstraints(lab, con); fieldPanel.add(lab); con.weighty = 1; gbl.setConstraints(optSP, con); fieldPanel.add(reqSP); fieldPanel.add(optSP); con.gridwidth = GridBagConstraints.REMAINDER; con.weighty = 0; gbl.setConstraints(typePanel, con); con.weighty = 1; gbl.setConstraints(fieldPanel, con); con.weighty = 0; gbl.setConstraints(messageLabel, con); panel.add(typePanel); panel.add(fieldPanel); panel.add(messageLabel); // Key bindings: ActionMap am = panel.getActionMap(); InputMap im = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); im.put(Globals.prefs.getKey("Close dialog"), "close"); am.put("close", new AbstractAction() { public void actionPerformed(ActionEvent e) { dispose(); } }); pack(); name.requestFocus(); } public EntryCustomizationDialog(JabRefFrame parent, BibtexEntryType type_) { this(parent); type = type_; } void initialize(){ getContentPane().setLayout(new BorderLayout()); getContentPane().add( buttonPanel, BorderLayout.SOUTH); getContentPane().add( panel, BorderLayout.CENTER); messageLabel.setForeground(Color.black); messageLabel.setText(Globals.lang("Delimit fields with semicolon, ex.") +": author;title;journal"); types_cb.addItemListener(this); } void save() { String typeName = name.getText().trim(); if (typeName.indexOf(" ") >= 0) { JOptionPane.showMessageDialog(ths, Globals.lang("The type name can not contain spaces."), Globals.lang("Illegal type name"), JOptionPane.ERROR_MESSAGE); return; } String reqStr = req_ta.getText().replaceAll("\\s+","") .replaceAll("\\n+","").trim(), optStr = opt_ta.getText().replaceAll("\\s+","") .replaceAll("\\n+","").trim(); if(! typeName.equals("")) { CustomEntryType typ = new CustomEntryType (Util.nCase(typeName), reqStr, optStr); BibtexEntryType.ALL_TYPES.put(typeName.toLowerCase(), typ); updateTypesForEntries(typ.getName()); setTypeSelection(); messageLabel.setText(Globals.lang("Stored definition for type")+ " '"+Util.nCase(typ.getName()) +"'."); } else{ messageLabel.setText(Globals.lang("You must fill in a name for the entry type.")); } } private void setTypeSelection() { types_cb.removeAllItems(); types_cb.addItem("<new>"); Iterator<String> i = BibtexEntryType.ALL_TYPES.keySet().iterator(); BibtexEntryType type; String toSet; while (i.hasNext()) { type = BibtexEntryType.getType(i.next()); toSet = Util.nCase(type.getName()); if (type instanceof CustomEntryType) toSet = toSet + " *"; types_cb.addItem(toSet); } } void makeButtons(){ ok = new JButton(Globals.lang("Store")); cancel=new JButton(Globals.lang("Close")); delete = new JButton(Globals.lang("Delete custom")); //genFields = new JButton(Globals.lang("Set general fields")); importTypes = new JButton(Globals.lang("Import")); exportTypes = new JButton(Globals.lang("Export")); buttonPanel.add( ok ); buttonPanel.add(delete); buttonPanel.add(Box.createHorizontalStrut(5)); //buttonPanel.add(genFields); buttonPanel.add(importTypes); buttonPanel.add(exportTypes); buttonPanel.add(Box.createHorizontalStrut(5)); buttonPanel.add( cancel); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { save(); } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); /*genFields.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { GenFieldsCustomizer gf = new GenFieldsCustomizer(parent, ths); Util.placeDialog(gf, parent); gf.show(); } });*/ delete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { BibtexEntryType type = BibtexEntryType .getType(name.getText()); if (type == null) messageLabel.setText(Globals.lang("There is no entry type")+ " '"+Util.nCase(name.getText())+ "' "+Globals.lang("defined.")); else if (!(type instanceof CustomEntryType)) messageLabel.setText("'"+type.getName()+"' "+ Globals.lang("is a standard type.")); else { String nm = name.getText(); if (BibtexEntryType.getStandardType(nm) == null) { int reply = JOptionPane.showConfirmDialog (parent, Globals.lang("All entries of this " +"type will be declared " +"typeless. Continue?"), Globals.lang("Delete custom format")+ " '"+Util.nCase(nm)+"'", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (reply != JOptionPane.YES_OPTION) return; } BibtexEntryType.removeType(nm); setTypeSelection(); updateTypesForEntries(Util.nCase(nm)); messageLabel.setText (Globals.lang("Removed entry type.")); } } }); exportTypes.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String filename = FileDialogs.getNewFile (parent.getFrame(), new File(System.getProperty("user.home")), ".txt", JFileChooser.SAVE_DIALOG, false); if (filename == null) return; File file = new File(filename); if (!file.exists() || (JOptionPane.showConfirmDialog (ths, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"), Globals.lang("Export entry types"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION)) { try { FileWriter out = new FileWriter(file); Iterator<String> i=BibtexEntryType.ALL_TYPES.keySet().iterator(); while (i.hasNext()) { Object o=BibtexEntryType.ALL_TYPES.get(i.next()); if (o instanceof CustomEntryType) { // Store this entry type. ((CustomEntryType)o).save(out); } } out.close(); } catch (IOException ex) { JOptionPane.showMessageDialog (ths, Globals.lang("Could not export entry types")+": "+ex.getMessage(), Globals.lang("Export preferences"), JOptionPane.ERROR_MESSAGE); //ex.printStackTrace(); } } } }); importTypes.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String filename = FileDialogs.getNewFile (parent.getFrame(), new File(System.getProperty("user.home")), ".txt", JFileChooser.OPEN_DIALOG, false); if (filename == null) return; try { BufferedReader in = new BufferedReader(new FileReader(new File(filename))); String line; int count = 0; while ((line = in.readLine()) != null) { line = line.trim(); if ((line.length() > 9+GUIGlobals.ENTRYTYPE_FLAG.length()) && line.substring(0, 9+GUIGlobals.ENTRYTYPE_FLAG.length()).equals("@comment{"+GUIGlobals.ENTRYTYPE_FLAG) && line.substring(line.length()-1).equals("}")) { // Matches a @comment{jabref-entrytype: ...} section. CustomEntryType type = CustomEntryType.parseEntryType(line.substring(9, line.length()-1)); if (type != null) { // Parsing succeeded. BibtexEntryType.ALL_TYPES.put(type.getName().toLowerCase(), type); count++; } } if (count > 0) { setTypeSelection(); req_ta.setText(""); opt_ta.setText(""); name.setText(""); messageLabel.setText(Globals.lang("Imported entry types")+": "+count); } } } catch (IOException ex) { JOptionPane.showMessageDialog (ths, Globals.lang("Could not import entry types")+": "+ex.getMessage(), Globals.lang("Import entry types"), JOptionPane.ERROR_MESSAGE); //ex.printStackTrace(); } } }); } /** * Cycle through all databases, and make sure everything is updated with * the new type customization. This includes making sure all entries have * a valid type, that no obsolete entry editors are around, and that * the right-click menus' change type menu is up-to-date. */ private void updateTypesForEntries(String typeName) { if (parent.tabbedPane.getTabCount() == 0) return; messageLabel.setText(Globals.lang("Updating entries...")); BibtexDatabase base; for (int i=0; i<parent.tabbedPane.getTabCount(); i++) { BasePanel bp = (BasePanel)parent.tabbedPane.getComponentAt(i); boolean anyChanges = false; bp.entryEditors.remove(typeName); //bp.rcm.populateTypeMenu(); // Update type menu for change type. base = bp.database; for (BibtexEntry e : base.getEntries()){ anyChanges = anyChanges | !e.updateType(); } if (anyChanges) { bp.markBaseChanged(); } } } public void itemStateChanged(ItemEvent e) { if (types_cb.getSelectedIndex() > 0) { // User has selected one of the existing types. String name = (String)types_cb.getSelectedItem(); updateToType((name.split(" "))[0]); } else { name.setText(""); req_ta.setText(""); opt_ta.setText(""); name.requestFocus(); } } public void updateToType(String o) { BibtexEntryType type = BibtexEntryType.getType(o); name.setText(type.getName()); req_ta.setText(Util.stringArrayToDelimited (type.getRequiredFields(), ";\n")); opt_ta.setText(Util.stringArrayToDelimited (type.getOptionalFields(), ";\n")); req_ta.requestFocus(); } }