1 package org.convey; 2 3 import javax.swing.*; 4 import javax.swing.text.*; 5 6 import java.awt.*; 7 8 import java.awt.event.*; 9 10 import com.echomine.jabber.*; 11 import com.echomine.common.*; 12 import com.echomine.net.*; 13 14 import org.jdom.*; 15 16 import java.util.*; 17 18 import java.text.*; 19 20 /** 21 * @author Andy Ames 22 * @version 0.3 23 */ 24 public class JabberCanvasPanel extends CanvasPanel implements ActionListener { 25 26 protected boolean autoScrollChatHistory = true; 27 28 protected boolean initiator; 29 30 protected boolean requestPen = false; 31 32 protected boolean revokePen = false; 33 34 protected boolean deniedPen = false; 35 36 protected int timeout = -1; 37 38 /** 39 * Straight text chat text field. 40 */ 41 protected JTextField chatTextField; 42 43 /** 44 * Straight text chat history text pane. 45 */ 46 protected JTextPane chatHistoryTextPane; 47 48 protected JScrollPane chatHistoryScrollPane; 49 50 /** 51 * Jabber chat conversation thread identifier. This is non-null when the user 52 * is connected, has indicated a chat user that will receive messages sent, 53 * and at least one message has been sent to the user indicated. Otherwise, 54 * its null. 55 */ 56 protected String threadId = null; 57 58 /** 59 * Jabber chat user who will receive messages. This is non-null when the user 60 * is connected and has indicated a chat user that will receive messages sent. 61 * <p> 62 * This field consists of the username, an ampersand, and the server 63 * (johndoe@jabber.org). The Jabbber resource is not included. 64 * (johndoe@jabber.org/Convey is incorrect.) 65 */ 66 protected String to = null; 67 68 protected String subject = null; 69 JabberCanvasPanel(ConveyFrame conveyFrame, String to, String subject)70 public JabberCanvasPanel(ConveyFrame conveyFrame, String to, String subject) { 71 super(conveyFrame); 72 super.setNetworked(); 73 74 this.to = to; 75 76 if(subject != null) 77 this.subject = subject; 78 else 79 this.subject = ""; 80 81 this.threadId = String.valueOf(System.currentTimeMillis()); 82 83 super.graphicPanel.setHasPen(false); 84 } 85 JabberCanvasPanel(ConveyFrame conveyFrame, String to, String threadId, String subject)86 public JabberCanvasPanel(ConveyFrame conveyFrame, String to, String threadId, String subject) { 87 super(conveyFrame); 88 89 this.to = to; 90 91 this.threadId = threadId; 92 93 if(subject != null) 94 this.subject = subject; 95 else 96 this.subject = ""; 97 98 super.graphicPanel.setHasPen(false); 99 } 100 initCenterComponent()101 public void initCenterComponent() { 102 JPanel chatPanel = new JPanel(new BorderLayout(5, 5)); 103 104 this.chatHistoryTextPane = new JTextPane(); 105 this.chatHistoryTextPane.setEditable(false); 106 this.chatTextField = new JTextField(); 107 this.chatTextField.addActionListener(this); 108 109 this.chatHistoryScrollPane = new JScrollPane(this.chatHistoryTextPane, 110 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 111 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 112 MouseListener ml = new MouseAdapter() { 113 public void mouseReleased(MouseEvent e) { 114 JScrollBar scrollBar = (JScrollBar)e.getSource(); 115 if(scrollBar.getValue() + scrollBar.getModel().getExtent() == scrollBar.getMaximum()) 116 autoScrollChatHistory = true; 117 else 118 autoScrollChatHistory = false; 119 } 120 }; 121 this.chatHistoryScrollPane.getVerticalScrollBar().addMouseListener(ml); 122 123 chatPanel.add(this.chatHistoryScrollPane, BorderLayout.CENTER); 124 125 Box chatMessageBox = new Box(BoxLayout.X_AXIS); 126 JLabel messageLabel = new JLabel(" Message "); 127 chatMessageBox.add(messageLabel); 128 chatMessageBox.add(this.chatTextField); 129 chatPanel.add(chatMessageBox, BorderLayout.SOUTH); 130 131 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, super.graphicPanel, chatPanel); 132 splitPane.setDividerLocation(350); 133 134 super.add(splitPane, BorderLayout.CENTER); 135 super.setNetworked(); 136 } 137 138 /** 139 * Sends straight text message if the user is connected and has indicated a 140 * chat receiver and has typed text into chatTextField. 141 */ sendText()142 public void sendText() { 143 JabberSession session = super.conveyFrame.getJabberSession(); 144 if(session != null && this.to != null) { 145 if(this.chatTextField.getText().length() > 0) { 146 JabberConveyMessage msg = new JabberConveyMessage(); 147 msg.setThreadID(this.threadId); 148 if(this.subject != null) 149 msg.setSubject(this.subject); 150 msg.setTo(this.to); 151 msg.setFrom(super.conveyFrame.getFrom()); 152 msg.setBody(this.chatTextField.getText()); 153 try { 154 session.sendMessage(msg); 155 } catch(SendMessageFailedException e) { 156 e.printStackTrace(); 157 } 158 159 this.appendMessage(msg, Color.blue); 160 161 this.chatTextField.setText(""); 162 163 if(this.autoScrollChatHistory) { 164 JScrollBar scrollBar = this.chatHistoryScrollPane.getVerticalScrollBar(); 165 scrollBar.setValue(scrollBar.getMaximum() - scrollBar.getModel().getExtent()); 166 } 167 } 168 } 169 } 170 171 /** 172 * Action event receiver for when the user presses <Enter> while the 173 * chat text field has focus. 174 */ actionPerformed(ActionEvent e)175 public void actionPerformed(ActionEvent e) { 176 sendText(); 177 } 178 appendMessage(JabberConveyMessage msg, Color nameColor)179 public void appendMessage(JabberConveyMessage msg, Color nameColor) { 180 StringTokenizer tokenizer = new StringTokenizer(msg.getFrom(), "@"); 181 StringBuffer name = new StringBuffer(" <"); 182 name.append(tokenizer.nextToken()); 183 name.append('>'); 184 DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); 185 StringBuffer date = new StringBuffer(format.format(new Date())); 186 date.insert(0, '['); 187 date.append(']'); 188 StringBuffer message = new StringBuffer(" "); 189 message.append(msg.getBody()); 190 message.append('\n'); 191 192 // Need package name to avoid conflict with org.jdom.Document 193 javax.swing.text.Document doc = this.chatHistoryTextPane.getDocument(); 194 try { 195 SimpleAttributeSet set = new SimpleAttributeSet(); 196 StyleConstants.setForeground(set, Color.lightGray); 197 doc.insertString(doc.getLength(), date.toString(), set); 198 StyleConstants.setForeground(set, nameColor); 199 doc.insertString(doc.getLength(), name.toString(), set); 200 StyleConstants.setForeground(set, Color.black); 201 doc.insertString(doc.getLength(), message.toString(), set); 202 } catch(Exception e) { 203 e.printStackTrace(); 204 } 205 } 206 getThreadId()207 public String getThreadId() { 208 return this.threadId; 209 } 210 getSubject()211 public String getSubject() { 212 return this.subject; 213 } 214 getTo()215 public String getTo() { 216 return this.to; 217 } 218 handleMessage(JabberConveyMessage msg)219 public void handleMessage(JabberConveyMessage msg) { 220 if(msg.isConvey()) 221 super.graphicPanel.handleConveyElement(msg.getConveyElement()); 222 else if(msg.isPen()) 223 this.handlePenElement(msg.getPenElement()); 224 else { 225 this.appendMessage(msg, Color.red); 226 227 if(this.autoScrollChatHistory) { 228 JScrollBar scrollBar = this.chatHistoryScrollPane.getVerticalScrollBar(); 229 scrollBar.setValue(scrollBar.getMaximum() - scrollBar.getModel().getExtent()); 230 } 231 } 232 } 233 sendGraphicEvent(GraphicEvent event)234 public void sendGraphicEvent(GraphicEvent event) { 235 JabberSession session = super.getConveyFrame().getJabberSession(); 236 if(session != null && this.to != null) { 237 org.jdom.Element element = event.toElement(); 238 if(element != null) { 239 org.jdom.Element conveyElement = new org.jdom.Element("convey", JabberConveyMessage.CONVEY_XMLNS); 240 conveyElement.addContent(element); 241 242 JabberConveyMessage msg = new JabberConveyMessage(); 243 msg.setThreadID(this.threadId); 244 if(this.subject != null) 245 msg.setSubject(this.subject); 246 msg.setTo(this.to); 247 msg.setFrom(super.getConveyFrame().getFrom()); 248 msg.setConveyElement(conveyElement); 249 try { 250 session.sendMessage(msg); 251 } catch(SendMessageFailedException e) { 252 e.printStackTrace(); 253 } 254 } 255 } 256 } 257 setInitiator(boolean value)258 public void setInitiator(boolean value) { 259 this.initiator = value; 260 } 261 isInitiator()262 public boolean isInitiator() { 263 return this.initiator; 264 } 265 handlePenElement(org.jdom.Element penElement)266 public void handlePenElement(org.jdom.Element penElement) { 267 if(penElement.getChild("request") != null) { 268 this.requestPen = true; 269 if(this.getConveyFrame().getSelectedCanvasPanel() == this) 270 doRequest(); 271 } else if(penElement.getChild("revoke") != null) { 272 this.requestPen = false; 273 this.revokePen = true; 274 if(this.getConveyFrame().getSelectedCanvasPanel() == this) 275 doRevoke(); 276 } else if(penElement.getChild("yield") != null) { 277 this.requestPen = false; 278 this.revokePen = false; 279 super.graphicPanel.setHasPen(true); 280 } else if(penElement.getChild("granted") != null) { 281 this.requestPen = false; 282 this.revokePen = false; 283 super.graphicPanel.setHasPen(true); 284 } else if(penElement.getChild("denied") != null) { 285 this.deniedPen = true; 286 if(this.getConveyFrame().getSelectedCanvasPanel() == this) { 287 if(this.requestPen) 288 doRequest(); 289 } 290 } 291 292 super.getConveyFrame().updateButtons(); 293 } 294 doRequest()295 public void doRequest() { 296 if(super.graphicPanel.hasPen()) { 297 int res = JOptionPane.showConfirmDialog(this, this.to + " is requesting the Pen. Do you wish to grant Pen request?", "Pen Request", 298 JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, 299 ResourceLoader.loadImageIcon("org/convey/images/requestpen.png")); 300 if(res == JOptionPane.YES_OPTION) { 301 super.graphicPanel.flushGraphicEventQueue(); 302 super.graphicPanel.setHasPen(false); 303 this.sendPenEvent(new PenEvent(PenEvent.GRANTED)); 304 } else 305 this.sendPenEvent(new PenEvent(PenEvent.DENIED)); 306 } else if(this.deniedPen) { 307 JOptionPane.showConfirmDialog(this, this.to + " denied your Pen request.", "Pen Request", 308 JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE, 309 ResourceLoader.loadImageIcon("org/convey/images/requestpen.png")); 310 this.deniedPen = false; 311 } else 312 super.graphicPanel.setHasPen(true); 313 314 this.requestPen = false; 315 } 316 doRevoke()317 public void doRevoke() { 318 if(super.graphicPanel.hasPen()) { 319 super.graphicPanel.flushGraphicEventQueue(); 320 super.graphicPanel.setHasPen(false); 321 this.sendPenEvent(new PenEvent(PenEvent.YIELD)); 322 JOptionPane.showConfirmDialog(this, this.to + " is revoking the Pen.", "Pen Revoke", 323 JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE, 324 ResourceLoader.loadImageIcon("org/convey/images/revokepen.png")); 325 } 326 327 this.revokePen = false; 328 } 329 isRequest()330 public boolean isRequest() { 331 return this.requestPen; 332 } 333 isRevoke()334 public boolean isRevoke() { 335 return this.revokePen; 336 } 337 sendPenEvent(PenEvent event)338 public void sendPenEvent(PenEvent event) { 339 JabberSession session = super.getConveyFrame().getJabberSession(); 340 if(session != null && this.to != null) { 341 org.jdom.Element element = event.toElement(); 342 if(element != null) { 343 org.jdom.Element conveyElement = new org.jdom.Element("pen", JabberConveyMessage.CONVEY_XMLNS); 344 conveyElement.addContent(element); 345 346 JabberConveyMessage msg = new JabberConveyMessage(); 347 msg.setThreadID(this.threadId); 348 if(this.subject != null) 349 msg.setSubject(this.subject); 350 msg.setTo(this.to); 351 msg.setFrom(super.getConveyFrame().getFrom()); 352 msg.setConveyElement(conveyElement); 353 try { 354 session.sendMessage(msg); 355 } catch(SendMessageFailedException e) { 356 e.printStackTrace(); 357 } 358 } 359 } 360 } 361 penYield()362 void penYield() { 363 super.graphicPanel.flushGraphicEventQueue(); 364 365 super.graphicPanel.setHasPen(false); 366 this.sendPenEvent(new PenEvent(PenEvent.YIELD)); 367 368 super.getConveyFrame().updateButtons(); 369 } 370 penRequest()371 void penRequest() { 372 this.requestPen = true; 373 this.sendPenEvent(new PenEvent(PenEvent.REQUEST)); 374 } 375 penRevoke()376 void penRevoke() { 377 this.requestPen = false; 378 this.revokePen = true; 379 this.sendPenEvent(new PenEvent(PenEvent.REVOKE)); 380 } 381 382 }