View Javadoc

1   /*
2    * Created on 13 avr. 2005
3    * 
4    *   Magic-Project is a turn based strategy simulator
5    *   Copyright (C) 2003-2007 Fabrice Daugan
6    *
7    *   This program is free software; you can redistribute it and/or modify it 
8    * under the terms of the GNU General Public License as published by the Free 
9    * Software Foundation; either version 2 of the License, or (at your option) any
10   * later version.
11   *
12   *   This program is distributed in the hope that it will be useful, but WITHOUT 
13   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
15   * details.
16   *
17   *   You should have received a copy of the GNU General Public License along  
18   * with this program; if not, write to the Free Software Foundation, Inc., 
19   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   */
21  package net.sf.magicproject.ui.component;
22  
23  import java.awt.Color;
24  import java.awt.Cursor;
25  import java.awt.LayoutManager;
26  import java.awt.event.MouseEvent;
27  import java.awt.event.MouseListener;
28  import java.awt.event.MouseMotionListener;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.Vector;
32  
33  import javax.swing.text.BadLocationException;
34  import javax.swing.text.Document;
35  import javax.swing.text.SimpleAttributeSet;
36  import javax.swing.text.StyleConstants;
37  
38  import net.sf.magicproject.tools.WebBrowser;
39  import net.sf.magicproject.ui.UIHelper;
40  
41  
42  /***
43   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
44   * @since 0.83
45   */
46  public class ChatArea extends EditorPane implements MouseListener,
47  		MouseMotionListener {
48  
49  	/***
50  	 * Create a new instance of this class.
51  	 * 
52  	 * @param layout
53  	 *          the specified layout manager
54  	 */
55  	public ChatArea(LayoutManager layout) {
56  		setLayout(layout);
57  		// Load style TODO Load these settings from a .properties file
58  		color = Color.BLACK;
59  		StyleConstants.setForeground(style, color);
60  		StyleConstants.setFontSize(style, 12);
61  		StyleConstants.setBold(style, false);
62  		StyleConstants.setItalic(style, false);
63  		StyleConstants.setStrikeThrough(style, false);
64  		fEmoticonMap = new HashMap<String, String>();
65  		fEmoticonMap.put("(CHILL)", "chilled.gif");
66  		fEmoticonMap.put("(CHILLED)", "chilled.gif");
67  		fEmoticonMap.put("(CRAZY)", "crazy.gif");
68  		fEmoticonMap.put("%)", "crazy.gif");
69  		fEmoticonMap.put("%-)", "crazy.gif");
70  		fEmoticonMap.put("(G)", "google.gif");
71  		fEmoticonMap.put("(GOOGLE)", "google.gif");
72  		fEmoticonMap.put("O)", "google.gif");
73  		fEmoticonMap.put("0)", "google.gif");
74  		fEmoticonMap.put("(H)", "huh.gif");
75  		fEmoticonMap.put(":?", "rolleyes.gif");
76  		fEmoticonMap.put("(ROLL)", "rolleyes.gif");
77  		fEmoticonMap.put("8|", "what.gif");
78  		fEmoticonMap.put("8-|", "what.gif");
79  		fEmoticonMap.put(":|", "what.gif");
80  		fEmoticonMap.put(":-|", "what.gif");
81  		fEmoticonMap.put(":@", "worried.gif");
82  		fEmoticonMap.put(":-@", "worried.gif");
83  		fEmoticonMap.put(":P", "tongue.gif");
84  		fEmoticonMap.put(":-P", "tongue.gif");
85  		fEmoticonMap.put("(BLIND)", "blind.gif");
86  		fEmoticonMap.put("(WOW)", "ninja.gif");
87  		fEmoticonMap.put(":D", "wow.gif");
88  		fEmoticonMap.put(":-D", "wow.gif");
89  		fEmoticonMap.put("(NINJA)", "ninja.gif");
90  		fEmoticonMap.put("(CONF)", "confused.gif");
91  		fEmoticonMap.put(":S", "confused.gif");
92  		fEmoticonMap.put(":-S", "confused.gif");
93  		fEmoticonMap.put("(6)", "evil.gif");
94  		fEmoticonMap.put(":-)", "smile.gif");
95  		fEmoticonMap.put(":)", "smile.gif");
96  		fEmoticonMap.put(";)", "wink.gif");
97  		fEmoticonMap.put(";-)", "wink.gif");
98  		fEmoticonMap.put("(X)", "love.gif");
99  		fEmoticonMap.put(":O", "ohhmy.gif");
100 		fEmoticonMap.put(":-O", "ohhmy.gif");
101 		fEmoticonMap.put(":(", "cry.gif");
102 		fEmoticonMap.put(":-(", "cry.gif");
103 		fEmoticonMap.put(":'(", "cry.gif");
104 		fEmoticonMap.put(":'-(", "cry.gif");
105 		fEmoticonMap.put("(L)", "love.gif");
106 		fEmoticonMap.put("(ICOOL)", "cool.gif");
107 		fEmoticonMap.put("(COOL)", "cool.gif");
108 		fEmoticonMap.put("(LUV)", "love.gif");
109 		fEmoticonMap.put("(LOVE)", "love.gif");
110 	}
111 
112 	@Override
113 	public void append(int id, String text) {
114 		super.append(id, text);
115 		StyleConstants.setBold(style, bold);
116 		StyleConstants.setForeground(style, color);
117 		StyleConstants.setFontSize(style, 12);
118 		StyleConstants.setItalic(style, italic);
119 		StyleConstants.setStrikeThrough(style, strikeThrough);
120 		try {
121 			getDocument().insertString(getDocument().getLength(), text, style);
122 
123 			// Temporary patch code.
124 			String s = this.getDocument().getText(0, getDocument().getLength());
125 			int d1 = s.length();
126 			getDocument().insertString(this.getDocument().getLength(), "", style);
127 			replaceEmoticon(text, d1);
128 			replaceURL(text, d1);
129 		} catch (BadLocationException e) {
130 			e.printStackTrace();
131 		}
132 
133 		if (!locked) {
134 			setCaretPosition(getDocument().getLength());
135 		}
136 	}
137 
138 	/***
139 	 * Replace the URL content by a blue, underlined URL link.
140 	 * 
141 	 * @param msg
142 	 * @param stratIndex
143 	 */
144 	private void replaceURL(String msg, int stratIndex) {
145 		try {
146 			Document doc = this.getDocument();
147 			int lid = -1;
148 			boolean a1 = StyleConstants.isUnderline(style);
149 			Color a3 = StyleConstants.getForeground(style);
150 			StyleConstants.setUnderline(style, true);
151 			StyleConstants.setForeground(style, Color.BLUE);
152 			String recMsg = msg;
153 			while (true) {
154 				int index = -1;
155 				recMsg = doc.getText(stratIndex, doc.getLength() - stratIndex);
156 				index = recMsg.indexOf("http://", lid + 1);
157 				if (index != -1) {
158 					lid = index;
159 
160 					int endPoint = recMsg.indexOf(" ", lid + 1);
161 					int te1 = recMsg.indexOf("http://", lid + 1);
162 					int te2 = recMsg.indexOf("\n", lid + 1);
163 
164 					// System.out.println(te1+","+te2+","+endPoint);
165 					if (te1 != -1) {
166 						endPoint = Math.min(te1, endPoint);
167 						if (endPoint == -1) {
168 							endPoint = te1;
169 						}
170 					}
171 					if (te2 != -1) {
172 						endPoint = Math.min(te2, endPoint);
173 						if (endPoint == -1) {
174 							endPoint = te2;
175 						}
176 					}
177 
178 					if (endPoint == -1) {
179 						endPoint = recMsg.length() - 1;
180 					}
181 
182 					String anchor = doc.getText(stratIndex + lid, endPoint - lid);
183 					doc.remove(stratIndex + lid, endPoint - lid);
184 					doc.insertString(stratIndex + lid, anchor, style);
185 					doc.insertString(stratIndex + lid + anchor.length(), " ",
186 							new SimpleAttributeSet());
187 
188 					startIndex.add(new Integer(stratIndex + lid));
189 					endIndex.add(new Integer(stratIndex + endPoint));
190 					linkURL.add(anchor);
191 				} else {
192 					break;
193 				}
194 			}
195 			StyleConstants.setUnderline(style, a1);
196 			StyleConstants.setForeground(style, a3);
197 		} catch (Exception e) {
198 			System.out.println(e.getMessage());
199 		}
200 	}
201 
202 	/***
203 	 * Replace the emoticon strings by the corresponding icons.
204 	 * 
205 	 * @param msg
206 	 *          the message that contain the emoticon shortcuts.
207 	 * @param startIndex
208 	 *          index of <code>msg</code> within the current document.
209 	 */
210 	private void replaceEmoticon(String msg, int startIndex) {
211 		try {
212 			int lastId = -1;
213 			String recMsg = msg;
214 			final Iterator<String> it = fEmoticonMap.keySet().iterator();
215 			while (it.hasNext()) {
216 				final String key = it.next();
217 				/***
218 				 * Replace all occurences of <code>key</code> by the correponding
219 				 * emoticon.
220 				 */
221 				lastId = recMsg.indexOf(key, lastId);
222 				while (lastId != -1) {
223 					this.getDocument().remove(startIndex + lastId, key.length());
224 					this.setCaretPosition(startIndex + lastId);
225 					insertIcon(UIHelper.getIcon(fEmoticonMap.get(key)));
226 					recMsg = this.getDocument().getText(startIndex,
227 							getDocument().getLength() - startIndex);
228 					lastId = recMsg.indexOf(key, lastId);
229 				}
230 			}
231 		} catch (Exception e) {
232 			System.err.println(e.getMessage());
233 		}
234 	}
235 
236 	public void mouseClicked(MouseEvent e) {
237 		int idx = viewToModel(e.getPoint());
238 		for (int i = 0; i < startIndex.size(); i++) {
239 			int sp = startIndex.elementAt(i);
240 			int ep = endIndex.elementAt(i);
241 			if (idx >= sp & idx <= ep) {
242 				String url = linkURL.elementAt(i);
243 				try {
244 					WebBrowser.launchBrowser(url);
245 				} catch (Exception e1) {
246 					// Ignore this error
247 				}
248 				break;
249 			}
250 		}
251 	}
252 
253 	public void mouseMoved(MouseEvent e) {
254 		int idx = viewToModel(e.getPoint());
255 		int a = 0;
256 		for (int i = 0; i < startIndex.size(); i++) {
257 			int sp = startIndex.elementAt(i);
258 			int ep = endIndex.elementAt(i);
259 			if (idx >= sp & idx <= ep) {
260 				setCursor(new Cursor(Cursor.HAND_CURSOR));
261 				a++;
262 				break;
263 			}
264 		}
265 		if (a == 0) {
266 			setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
267 		}
268 	}
269 
270 	public void mouseDragged(MouseEvent arg0) {
271 		// TODO D&D in chat --> not yet implmented
272 	}
273 
274 	public void mousePressed(MouseEvent e) {
275 		// Ignore this event
276 	}
277 
278 	public void mouseReleased(MouseEvent e) {
279 		// Ignore this event
280 	}
281 
282 	public void mouseEntered(MouseEvent e) {
283 		// Ignore this event
284 	}
285 
286 	public void mouseExited(MouseEvent e) {
287 		// Ignore this event
288 	}
289 
290 	Color color;
291 
292 	boolean italic;
293 
294 	boolean strikeThrough;
295 
296 	boolean underLine;
297 
298 	boolean bold;
299 
300 	private HashMap<String, String> fEmoticonMap = null;
301 
302 	private Vector<Integer> startIndex = new Vector<Integer>();
303 
304 	private Vector<Integer> endIndex = new Vector<Integer>();
305 
306 	private Vector<String> linkURL = new Vector<String>();
307 
308 }