1 package net.sf.jabref.gui;
3 import net.sf.jabref.Globals;
5 import javax.swing.table.AbstractTableModel;
6 import javax.swing.event.TableModelEvent;
8 import java.util.ArrayList;
9 import java.util.Iterator;
12 * Data structure to contain a list of file links, parseable from a coded string.
13 * Doubles as a table model for the file list editor.
15 public class FileListTableModel extends AbstractTableModel {
17 private final ArrayList list = new ArrayList();
19 public FileListTableModel() {
22 public int getRowCount() {
28 public int getColumnCount() {
32 public Class getColumnClass(int columnIndex) {
36 public Object getValueAt(int rowIndex, int columnIndex) {
38 FileListEntry entry = (FileListEntry)list.get(rowIndex);
39 switch (columnIndex) {
40 case 0: return entry.getDescription();
41 case 1: return entry.getLink();
42 default: return entry.getType() != null ?
43 entry.getType().getName() : "";
48 public FileListEntry getEntry(int index) {
50 return (FileListEntry)list.get(index);
54 public void removeEntry(int index) {
57 fireTableRowsDeleted(index, index);
63 * Add an entry to the table model, and fire a change event. The change event
64 * is fired on the event dispatch thread.
65 * @param index The row index to insert the entry at.
66 * @param entry The entry to insert.
68 public void addEntry(final int index, final FileListEntry entry) {
70 list.add(index, entry);
71 if (!SwingUtilities.isEventDispatchThread()) {
72 SwingUtilities.invokeLater(new Runnable() {
74 fireTableRowsInserted(index, index);
78 fireTableRowsInserted(index, index);
83 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
87 * Set up the table contents based on the flat string representation of the file list
88 * @param value The string representation
90 public void setContent(String value) {
91 setContent(value, false);
94 private FileListEntry setContent(String value, boolean firstOnly) {
97 ArrayList newList = new ArrayList();
98 StringBuilder sb = new StringBuilder();
99 ArrayList thisEntry = new ArrayList();
100 boolean escaped = false;
101 for (int i=0; i<value.length(); i++) {
102 char c = value.charAt(i);
103 if (!escaped && (c == '\\')) {
107 else if (!escaped && (c == ':')) {
108 thisEntry.add(sb.toString());
109 sb = new StringBuilder();
111 else if (!escaped && (c == ';')) {
112 thisEntry.add(sb.toString());
113 sb = new StringBuilder();
115 return decodeEntry(thisEntry);
117 newList.add(decodeEntry(thisEntry));
125 thisEntry.add(sb.toString());
126 if (thisEntry.size() > 0) {
128 return decodeEntry(thisEntry);
130 newList.add(decodeEntry(thisEntry));
133 synchronized (list) {
135 list.addAll(newList);
137 fireTableChanged(new TableModelEvent(this));
143 * Convenience method for finding a label corresponding to the type of the
144 * first file link in the given field content. The difference between using
145 * this method and using setContent() on an instance of FileListTableModel
146 * is a slight optimization: with this method, parsing is discontinued after
147 * the first entry has been found.
148 * @param content The file field content, as fed to this class' setContent() method.
149 * @return A JLabel set up with no text and the icon of the first entry's file type,
150 * or null if no entry was found.
152 public static JLabel getFirstLabel(String content) {
153 FileListTableModel tm = new FileListTableModel();
154 FileListEntry entry = tm.setContent(content, true);
155 return entry != null ? entry.getType().getIconLabel() : null;
159 private FileListEntry decodeEntry(ArrayList contents) {
160 return new FileListEntry(getElementIfAvailable(contents, 0),
161 getElementIfAvailable(contents, 1),
162 Globals.prefs.getExternalFileTypeByName
163 (getElementIfAvailable(contents, 2)));
166 private String getElementIfAvailable(ArrayList contents, int index) {
167 if (index < contents.size())
168 return (String)contents.get(index);
173 * Transform the file list shown in the table into a flat string representable
175 * @return String representation.
177 public String getStringRepresentation() {
178 StringBuilder sb = new StringBuilder();
179 for (Iterator iterator = list.iterator(); iterator.hasNext();) {
180 FileListEntry entry = (FileListEntry) iterator.next();
181 sb.append(encodeEntry(entry));
182 if (iterator.hasNext())
185 return sb.toString();
189 * Transform the file list shown in the table into a HTML string representation
190 * suitable for displaying the contents in a tooltip.
191 * @return Tooltip representation.
193 public String getToolTipHTMLRepresentation() {
194 StringBuilder sb = new StringBuilder("<html>");
195 for (Iterator iterator = list.iterator(); iterator.hasNext();) {
196 FileListEntry entry = (FileListEntry) iterator.next();
197 sb.append(entry.getDescription()).append(" (").append(entry.getLink()).append(')');
198 if (iterator.hasNext())
201 return sb.append("</html>").toString();
204 private String encodeEntry(FileListEntry entry) {
205 StringBuilder sb = new StringBuilder();
206 sb.append(encodeString(entry.getDescription()));
208 sb.append(encodeString(entry.getLink()));
210 sb.append(encodeString(entry.getType() != null ? entry.getType().getName() : ""));
211 return sb.toString();
214 private String encodeString(String s) {
215 StringBuilder sb = new StringBuilder();
216 for (int i=0; i<s.length(); i++) {
217 char c = s.charAt(i);
218 if ((c == ';') || (c == ':') || (c == '\\'))
222 return sb.toString();
225 public void print() {
226 System.out.println("----");
227 for (Iterator iterator = list.iterator(); iterator.hasNext();) {
228 FileListEntry fileListEntry = (FileListEntry) iterator.next();
229 System.out.println(fileListEntry);
231 System.out.println("----");