1   /**
2    * JHylaFax - A java client for HylaFAX.
3    *
4    * Copyright (C) 2005 by Steffen Pingel <steffenp@gmx.de>
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19   */
20  package net.sf.jhylafax;
21  
22  import static net.sf.jhylafax.JHylaFAX.i18n;
23  import java.awt.BorderLayout;
24  import java.awt.FlowLayout;
25  import java.awt.event.ActionEvent;
26  import java.io.File;
27  import java.io.IOException;
28  import java.util.Date;
29  import javax.swing.Action;
30  import javax.swing.JFileChooser;
31  import javax.swing.JMenuItem;
32  import javax.swing.JOptionPane;
33  import javax.swing.JPanel;
34  import javax.swing.JPopupMenu;
35  import javax.swing.JScrollPane;
36  import javax.swing.JTable;
37  import javax.swing.ListSelectionModel;
38  import javax.swing.event.ListSelectionEvent;
39  import javax.swing.event.ListSelectionListener;
40  import javax.swing.table.TableModel;
41  import net.sf.jhylafax.JobHelper.FileStat;
42  import net.sf.jhylafax.fax.FaxJob;
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  import org.xnap.commons.gui.ColoredTable;
46  import org.xnap.commons.gui.Dialogs;
47  import org.xnap.commons.gui.action.AbstractXNapAction;
48  import org.xnap.commons.gui.table.FilesizeCellRenderer;
49  import org.xnap.commons.gui.table.StringCellRenderer;
50  import org.xnap.commons.gui.table.TableLayout;
51  import org.xnap.commons.gui.table.TableSorter;
52  import org.xnap.commons.gui.util.GUIHelper;
53  import org.xnap.commons.gui.util.PopupListener;
54  import org.xnap.commons.settings.SettingStore;
55  import org.xnap.commons.util.StringHelper;
56  
57  /**
58   * A generic panel that displays a list of {@link net.sf.jhylafax.fax.FaxJob} 
59   * objects in a table.
60   *  
61   * @author Steffen Pingel
62   */
63  public abstract class AbstractQueuePanel extends JPanel implements ListSelectionListener, LocaleChangeListener {
64  	
65  	private final static Log logger = LogFactory.getLog(AbstractQueuePanel.class);
66  	
67  	private String[] defaultColumns;
68  	private String queueName;
69  	private ColoredTable queueTable;
70  	private TableLayout queueTableLayout;
71  	private ResetQueueTableAction resetQueueTableAction;
72  	private JPanel buttonPanel;
73  	private JPopupMenu tablePopupMenu;
74  
75  	public AbstractQueuePanel(String queueName) {
76  		this.queueName = queueName;
77  		
78  		setLayout(new BorderLayout());
79  		setBorder(GUIHelper.createEmptyBorder(10));
80  				
81  		resetQueueTableAction = new ResetQueueTableAction();
82  		
83  		tablePopupMenu = new JPopupMenu();
84  		
85  		TableSorter sorter = new TableSorter(getTableModel());
86  		queueTable = new ColoredTable(sorter);
87  		queueTableLayout = new TableLayout(queueTable);
88  		initializeTableLayout();
89  		queueTableLayout.getHeaderPopupMenu().add(new JMenuItem(resetQueueTableAction));
90  		add(new JScrollPane(queueTable), BorderLayout.CENTER);
91  
92  		queueTable.setShowVerticalLines(true);
93  		queueTable.setShowHorizontalLines(false);
94  		queueTable.setAutoCreateColumnsFromModel(true);
95  		queueTable.setIntercellSpacing(new java.awt.Dimension(2, 1));
96  		queueTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
97  		queueTable.getSelectionModel().addListSelectionListener(this);
98  		queueTable.addMouseListener(new PopupListener(tablePopupMenu));
99  		
100 		queueTable.setDefaultRenderer(Long.class, new FilesizeCellRenderer());
101 		queueTable.setDefaultRenderer(String.class, new StringCellRenderer());
102 		queueTable.setDefaultRenderer(Date.class, new TimeCellRenderer());
103 		queueTable.setDefaultRenderer(FaxJob.State.class, new StateCellRenderer());
104 		
105 		buttonPanel = new JPanel(new FlowLayout());
106 		add(buttonPanel, BorderLayout.SOUTH);
107 	}
108 	
109 	protected File createTempFile(String filename)
110 	{
111 		try {
112 			// TODO should preserve extension of downloaded file
113 			File tempFile = File.createTempFile("jhylafax", null);
114 			tempFile.deleteOnExit();
115 			return tempFile;
116 		}
117 		catch (IOException e) {
118 			logger.debug("Error creating temporary file", e);
119 			JHylaFAX.getInstance().showError(i18n.tr("Error creating temporary file"), e);
120 			return null;				
121 		}			
122 	}
123 	
124 	public String getAbsolutePath(String filename) {
125 		return getQueueName() + "/" + filename;
126 	}	
127 
128 	public String getQueueName() {
129 		return queueName;
130 	}
131 	
132 	public abstract FileStat getSelectedFile();
133 	
134 	protected abstract TableModel getTableModel();
135 	
136 	protected TableLayout getTableLayout() {
137 		return queueTableLayout;
138 	}
139 
140 	protected JTable getTable() {
141 		return queueTable;
142 	}
143 	
144 	protected JPopupMenu getTablePopupMenu() {
145 		return tablePopupMenu;
146 	}
147 	
148 	protected JPanel getButtonPanel() {
149 		return buttonPanel;
150 	}
151 
152 	protected int getSelectedRow() {
153 		int row = queueTable.getSelectedRow();
154 		return (row == -1) ? -1 : ((TableSorter)queueTable.getModel()).mapToIndex(row);
155 	}
156 
157 	protected abstract void initializeTableLayout();
158 
159 	public void restoreLayout(SettingStore store, String[] defaultColumns) {
160 		this.defaultColumns = defaultColumns;
161 		
162 		store.restoreTable(getQueueName(), defaultColumns, queueTableLayout);
163 	}	
164 
165 	public void saveLayout(SettingStore store) {
166 		store.saveTable(getQueueName(), queueTableLayout);
167 	}
168 	
169 	public abstract void updateActions();
170 
171 	public void updateLabels() {
172 		resetQueueTableAction.putValue(Action.NAME, i18n.tr("Reset to Defaults"));
173 	}
174 
175 	public void resetTable() {
176 		initializeTableLayout();
177 		getTableLayout().setColumnsVisible(defaultColumns);	
178 		queueTable.getTableHeader().revalidate();
179 	}
180 	
181 	public void valueChanged(ListSelectionEvent e) {
182 		updateActions();
183 	}
184 
185 	protected class DeleteAction extends AbstractXNapAction {
186 		
187 		public DeleteAction() {
188 			putValue(ICON_FILENAME, "editdelete.png");
189 		}
190 
191 		public void actionPerformed(ActionEvent e)
192 		{
193 			FileStat selectedFile = getSelectedFile();
194 			if (selectedFile == null) {
195 				return;
196 			}
197 
198 			if (Dialogs.showConfirmDialog(JHylaFAX.getInstance(), 
199 					i18n.tr("Do you really want to delete the file {0}?", selectedFile.filename),
200 					i18n.tr("Delete File"), 
201 					JOptionPane.YES_NO_OPTION, 
202 					Settings.CONFIRM_DELETE) == JOptionPane.YES_OPTION) {
203 				JobHelper.delete(getAbsolutePath(selectedFile.filename));
204 			}
205 		}
206 
207 		public void updateLabels() {
208 			putValue(Action.NAME, i18n.tr("Delete"));
209 		}
210 		
211 	}
212 
213 	protected class ResetQueueTableAction extends AbstractXNapAction {
214 		
215 		public ResetQueueTableAction() {
216 		}
217 
218 		public void actionPerformed(ActionEvent event) {
219 			resetTable();
220 		}
221 		
222 	}
223 	
224 	protected class SaveAction extends AbstractXNapAction {
225 		
226 		public SaveAction() {
227 			putValue(ICON_FILENAME, "filesaveas.png");
228 		}
229 
230 		public void actionPerformed(ActionEvent e)
231 		{
232 			FileStat selectedFile = getSelectedFile();
233 			if (selectedFile == null) {
234 				return;
235 			}
236 			
237 			JFileChooser chooser = new JFileChooser();
238 			chooser.setSelectedFile(new File(StringHelper.lastToken(selectedFile.filename, "/")));
239 			if (chooser.showSaveDialog(JHylaFAX.getInstance()) == JFileChooser.APPROVE_OPTION) {
240 				// TODO show warning, if file exists
241 				JobHelper.save(chooser.getSelectedFile(), 
242 						getAbsolutePath(selectedFile.filename),	selectedFile.filesize);
243 			}
244 		}
245 		
246 		public void updateLabels() {
247 			putValue(Action.NAME, i18n.tr("Save"));
248 		}
249 
250 	}
251 	
252 	protected class ViewAction extends AbstractXNapAction {
253 		
254 		public ViewAction() {
255 			putValue(ICON_FILENAME, "viewmag.png");
256 		}
257 
258 		public void actionPerformed(ActionEvent event)
259 		{
260 			FileStat selectedFile = getSelectedFile();
261 			if (selectedFile == null) {
262 				return;
263 			}
264 			
265 			String viewerPath = JHylaFAXHelper.getViewerPath(getQueueName());
266 			if (viewerPath != null) {
267 				File tempFile = createTempFile(selectedFile.filename);
268 				if (tempFile != null
269 						&& JobHelper.save(tempFile, getAbsolutePath(selectedFile.filename), selectedFile.filesize)) {
270 					JHylaFAXHelper.view(viewerPath, new File[] { tempFile });
271 				}
272 			}
273 		}
274 
275 		public void updateLabels() {
276 			putValue(Action.NAME, i18n.tr("View"));
277 			putValue(Action.LONG_DESCRIPTION, 
278 					i18n.tr("The selected file is opened in an external viewer."));
279 		}
280 		
281 	}
282 	
283 }