View Javadoc

1   /*
2    *  XNap Commons
3    *
4    *  Copyright (C) 2005  Felix Berger
5    *  Copyright (C) 2005  Steffen Pingel
6    *
7    *  This library is free software; you can redistribute it and/or
8    *  modify it under the terms of the GNU Lesser General Public
9    *  License as published by the Free Software Foundation; either
10   *  version 2.1 of the License, or (at your option) any later version.
11   *
12   *  This library is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   *  Lesser General Public License for more details.
16   *
17   *  You should have received a copy of the GNU Lesser General Public
18   *  License along with this library; if not, write to the Free Software
19   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   */
21  package org.xnap.commons.gui;
22  
23  import java.awt.BorderLayout;
24  import java.awt.Color;
25  import java.awt.Component;
26  import java.awt.Cursor;
27  import java.awt.Dimension;
28  import java.awt.Font;
29  import java.util.Hashtable;
30  import java.util.Map;
31  import javax.swing.Icon;
32  import javax.swing.JComponent;
33  import javax.swing.JDialog;
34  import javax.swing.JEditorPane;
35  import javax.swing.JFrame;
36  import javax.swing.JLabel;
37  import javax.swing.JPanel;
38  import javax.swing.JScrollPane;
39  import javax.swing.JTabbedPane;
40  import javax.swing.JTextArea;
41  import javax.swing.border.EmptyBorder;
42  import javax.swing.event.HyperlinkEvent;
43  import javax.swing.event.HyperlinkListener;
44  import javax.swing.text.JTextComponent;
45  import org.xnap.commons.gui.util.GUIHelper;
46  import org.xnap.commons.i18n.I18nFactory;
47  
48  /***
49   * Simple about dialog. A {@link JTabbedPane} is used as the main widget and
50   * methods are provided to add tabs that contain a file, e.g. the software 
51   * license.  
52   */
53  public class AboutDialog extends DefaultDialog {
54  
55      private CloseableTabbedPane tabbedPane;
56      private Map<String, JComponent> tabByFilename = new Hashtable<String, JComponent>();
57      
58      /***
59       * Constructs an empty dialog with a single close button.
60       * 
61       * @param owner the dialog owner
62       */
63      public AboutDialog(JDialog owner)
64      {
65  		super(owner, BUTTON_CLOSE);
66  
67  		initialize();
68      }
69  
70      /***
71       * Constructs an empty dialog with a single close button.
72       * 
73       * @param owner the dialog owner
74       */
75      public AboutDialog(JFrame owner)
76      {
77  		super(owner, BUTTON_CLOSE);
78  
79  		initialize();
80      }
81  
82      /***
83       * Constructs an empty dialog with a single close button.
84       */
85      public AboutDialog()
86      {
87  		super(BUTTON_CLOSE);
88  
89  		initialize();
90      }
91  
92      private void initialize()
93      {
94  		tabbedPane = new CloseableTabbedPane();
95          tabbedPane.setPreferredSize(new Dimension(600, 300));
96  		tabbedPane.setCloseListener(new CloseableTabbedPane.CloseListener() {
97  			public void closeRequested(Component component)
98  			{
99  				tabbedPane.remove(component);
100 				tabByFilename.values().remove(component);
101 			}
102 		});
103         
104 		setMainComponent(tabbedPane);
105 		setButtonSeparatorVisible(false);
106         pack();
107     }
108 
109 	/***
110 	 * Adds a tab that displays an image that is followed by a file's content.
111 	 *  
112 	 * @param title the title of the tab
113 	 * @param image the image
114 	 * @param filename the name of the file to display
115 	 * @param alternativeMessage the text that is displayed if 
116 	 * <code>filename</code> can not be read
117 	 * @return the text area that was added to the created tab 
118 	 * @see GUIHelper#showFile(JTextComponent, String, String)
119 	 */
120 	public JTextArea addLogoTab(String title, Icon image, String filename, String alternativeMessage, boolean closeable)
121 	{
122 		JPanel panel = new JPanel();
123 		panel.setBackground(Color.white);
124 		panel.setLayout(new BorderLayout());
125 		JLabel logoLabel = new JLabel(image);
126 		logoLabel.setBorder(new EmptyBorder(5, 5, 5, 5));
127 		panel.add(logoLabel, BorderLayout.NORTH);
128 		JTextArea textArea = new JTextArea(5, 40);
129 		textArea .setEditable (false);
130 		textArea .setBorder(new EmptyBorder(5, 5, 5, 5));
131 		panel.add(textArea , BorderLayout.CENTER);
132 		addTabInternal(textArea, title, filename, alternativeMessage, closeable);
133 		return textArea ;
134 	}
135 
136 	/***
137 	 * Adds a tab that displays an image that is followed by a file's content.
138 	 *  
139 	 * @param title the title of the tab
140 	 * @param image the image
141 	 * @param filename the name of the file to display
142 	 * @return the text area that was added to the created tab 
143 	 * @see #addLogoTab(String, Icon, String, String, boolean)
144 	 */
145 	public JTextArea addLogoTab(String title, Icon image, String filename)
146 	{
147 		return addLogoTab(title, image, filename, getFileNotFoundMessage(filename), false);
148 	}
149 
150 	/***
151 	 * Adds a tab that displays a file's content.
152 	 *  
153 	 * @param title the title of the tab
154 	 * @param filename the name of the file to display
155 	 * @param alternativeMessage the text that is displayed if 
156 	 * <code>filename</code> can not be read
157 	 * @return the text area that was added to the created tab 
158 	 * @see GUIHelper#showFile(JTextComponent, String, String)
159 	 */
160 	public JTextArea addTab(String title, String filename, String alternativeMessage, boolean closeable) 
161 	{
162 		JTextArea textArea = new JTextArea(15, 40);
163 		textArea.setBorder(new EmptyBorder(5, 5, 5, 5));
164 		textArea.setEditable (false);
165 		addTabInternal(textArea, title, filename, alternativeMessage, closeable);
166 		return textArea;
167 	}
168 
169 	/***
170 	 * Adds a tab that displays a file's content.
171 	 *  
172 	 * @param title the title of the tab
173 	 * @param filename the name of the file to display
174 	 * @return the text area that was added to the created tab 
175 	 * @see #addTab(String, String, String, boolean)
176 	 */
177 	public JTextArea addTab(String title, String filename)
178 	{
179 		return addTab(title, filename, getFileNotFoundMessage(filename), false);
180 	}
181 	
182 	public JEditorPane addHTMLTab(String title, String filename, String alternativeMessage, boolean closeable, boolean followHyperlinks)
183 	{
184 		JEditorPane editorPane = new JEditorPane();
185 		editorPane.setContentType("text/html");
186 		editorPane.setEditable(false);
187 		if (followHyperlinks) {
188 			editorPane.addHyperlinkListener(new LicenseLinkListener());
189 			//editorPane.addMouseMotionListener(new MouseLinkListener());
190 		}
191 		editorPane.setBorder(GUIHelper.createEmptyBorder(5));
192 		addTabInternal(editorPane, title, filename, alternativeMessage, closeable);
193 		return editorPane;
194 	}
195 
196 	public JEditorPane addHTMLTab(String title, String filename, boolean followHyperlinks)
197 	{
198 		return addHTMLTab(title, filename, getFileNotFoundMessage(filename), false, followHyperlinks);
199 	}
200 
201 	private void addTabInternal(JTextComponent component, String title, String filename, String alternativeMessage, boolean closeable)
202 	{
203 		JScrollPane scrollPane = new JScrollPane(component);
204 		GUIHelper.showFile(component, filename, alternativeMessage); 
205 		getTabbedPane().addTab(title, scrollPane, null, closeable);
206 		tabByFilename.put(filename, scrollPane);	
207 	}
208 	
209 	/***
210 	 * Returns the main widget.
211 	 */
212 	public CloseableTabbedPane getTabbedPane() 
213 	{
214 		return tabbedPane;
215 	}
216 
217 	public String getFileNotFoundMessage(String filename)
218 	{
219 		return I18nFactory.getI18n(AboutDialog.class).tr("File {0} not found", 
220 				filename);
221 	}
222 	
223 	/***
224      * Adds a new license tab.
225      *
226      * License files are supposed to be pure text files.
227      *
228      * @param name of the license
229      * @param filename filename of the license text to load
230      */
231     public Component getOrAddTab(String name, String filename)
232     {
233 		JComponent c = tabByFilename.get(filename);
234 		if (c == null) {
235 			if (filename.endsWith("html") || filename.endsWith("htm")) {
236 				addHTMLTab(name, filename, getFileNotFoundMessage(filename), true, false);
237 			}
238 			else {
239 				JTextArea textArea = addTab(name, filename, getFileNotFoundMessage(filename), true);
240 				textArea.setFont(new Font("Monospaced", Font.PLAIN, 10));
241 			}
242 			// need to return the scroll pane, therefore repeat the look up
243 			c = tabByFilename.get(filename);
244 		}
245 		return c;
246     }
247     
248     /***
249      * Listens for hyperlink events and switches the panels of the tabbed pain
250      * when the link description matches a license displayed in one of the
251      * panels.
252      */
253     private class LicenseLinkListener implements HyperlinkListener
254     {
255 		public void hyperlinkUpdate(HyperlinkEvent event)
256 		{
257 			if (event.getDescription() == null) {
258 				return;
259 			}
260 			
261 			if (event.getEventType() == HyperlinkEvent.EventType.ENTERED) {
262 				setCursor(event, Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
263 			}
264 			else if (event.getEventType() == HyperlinkEvent.EventType.EXITED) {
265 				setCursor(event, null);
266 			}
267 			else if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
268 				setCursor(event, null);
269 				
270 				Component c = getOrAddTab(event.getDescription(), event.getDescription()); 
271 				tabbedPane.setSelectedComponent(c);
272 			}
273 		}
274 		
275 		private void setCursor(HyperlinkEvent event, Cursor cursor)
276 		{
277 			JEditorPane pane = (JEditorPane)event.getSource();
278 			// XXX does not work under Linux
279 			// pane.setCursor(null);
280 			AboutDialog.this.setCursor(cursor);			
281 		}
282 		
283     }
284        
285 }