001 /*
002 Copyright (C) 2003 Adam Olsen
003 This program is free software; you can redistribute it and/or modify
004 it under the terms of the GNU General Public License as published by
005 the Free Software Foundation; either version 1, or (at your option)
006 any later version.
007 This program is distributed in the hope that it will be useful,
008 but WITHOUT ANY WARRANTY; without even the implied warranty of
009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010 GNU General Public License for more details.
011 You should have received a copy of the GNU General Public License
012 along with this program; if not, write to the Free Software
013 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
014 */
015 package com.valhalla.jbother;
016
017 import com.valhalla.jbother.*;
018 import com.valhalla.jbother.BuddyList;
019 import com.valhalla.gui.*;
020 import com.valhalla.jbother.jabber.*;
021 import com.valhalla.jbother.groupchat.*;
022 import javax.swing.*;
023 import java.awt.*;
024 import java.awt.event.*;
025 import java.util.*;
026 import net.infonode.tabbedpanel.*;
027 import net.infonode.tabbedpanel.titledtab.*;
028 import net.infonode.util.*;
029
030 import org.jivesoftware.smack.packet.*;
031 import org.jivesoftware.smack.*;
032
033 /**
034 * A blank message window - to send "NORMAL" type messages
035 *
036 * @author Adam Olsen
037 * @created March 2, 2005
038 * @version 1.0
039 */
040 public class MessagePanel extends ConversationPanel implements TabFramePanel
041 {
042 private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() );
043 private JLabel toLabel = new JLabel( resources.getString( "to" ) + ": " );
044 private JLabel subjectLabel = new JLabel( resources.getString( "subject" ) + ": " );
045 private JButton sendButton = new JButton( resources.getString( "send" ) );
046 private JButton replyButton = new JButton( resources.getString( "reply" ) );
047 private JButton replyQuoteButton = new JButton( resources.getString( "replyQuote" ) );
048 private MJTextField toField = new MJTextField();
049 private MJTextField subjectField = new MJTextField();
050 private MJTextArea textEntryArea = new MJTextArea();
051 private JPanel buttonPanel = new JPanel();
052 JScrollPane scroll = new JScrollPane(textEntryArea);
053
054 private Message receivedMessage = null;
055 private String from = "";
056 private TitledTab tab;
057
058 /**
059 * Description of the Field
060 */
061 public final static String QUOTE_STRING = ">";
062 /**
063 * Description of the Field
064 */
065 public final static String RECIPIENTS_DELIMITER = ";";
066 // character that separates recipients of the message
067
068
069 /**
070 * Default constructor
071 */
072 public MessagePanel()
073 {
074 super( null );
075
076 setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
077 setLayout( new BorderLayout( 5, 5 ) );
078
079 JPanel topPanel = new JPanel();
080 topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS ) );
081
082 JPanel toPanel = new JPanel( new BorderLayout( 5, 5 ) );
083 toPanel.add( toLabel, BorderLayout.WEST );
084 toPanel.add( toField, BorderLayout.CENTER );
085 toPanel.setBorder( BorderFactory.createEmptyBorder( 0, 0, 5, 0 ) );
086 topPanel.add( toPanel );
087
088 JPanel subjectPanel = new JPanel( new BorderLayout( 5, 5 ) );
089 subjectPanel.add( subjectLabel, BorderLayout.WEST );
090 subjectPanel.add( subjectField, BorderLayout.CENTER );
091 topPanel.add( subjectPanel );
092 textEntryArea.setWrapStyleWord( true );
093 textEntryArea.setLineWrap( true );
094
095 add( topPanel, BorderLayout.NORTH );
096
097
098 add( scroll, BorderLayout.CENTER );
099
100 buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.X_AXIS ) );
101 buttonPanel.add( Box.createHorizontalGlue() );
102 buttonPanel.add( sendButton );
103 from = BuddyList.getInstance().getConnection().getUser();
104
105 addListeners();
106
107 add( buttonPanel, BorderLayout.SOUTH );
108
109 toField.grabFocus();
110 }
111
112 public void setTab( TitledTab tab ) { this.tab = tab; }
113 public TitledTab getTab() { return tab; }
114
115 public void setBuddy( BuddyStatus buddy ) { this.buddy = buddy; }
116
117 /**
118 */
119 public void createFrame()
120 {
121 frame = new JFrame();
122 frame.setContentPane( this );
123
124 frame.pack();
125 frame.setSize( new Dimension( 450, 370 ) );
126
127 frame.setIconImage( Standard.getImage( "frameicon.png" ) );
128
129 Standard.cascadePlacement( frame );
130
131 frame.addWindowListener(
132 new WindowAdapter()
133 {
134 public void windowClosing( WindowEvent e )
135 {
136 closeHandler();
137 }
138 } );
139 }
140
141 /**
142 * Gets the buddy attribute of the MessagePanel object
143 *
144 * @return The buddy value
145 */
146 public BuddyStatus getBuddy()
147 {
148 String from = "unknown";
149 from = toField.getText();
150 if( from.equals( "" ) )
151 {
152 from = "unknown";
153 }
154 BuddyStatus buddy = BuddyList.getInstance().getBuddyStatus( from );
155 return buddy;
156 }
157
158 /**
159 * Receives a message and displays it in the Dialog
160 *
161 * @param message the message packet to receive
162 */
163 public void receiveMessage( Message message )
164 {
165 toLabel.setText( resources.getString( "from" ) + ": " );
166 toField.setText( message.getFrom() );
167 toField.setEditable( false );
168 // to and subject fields are disabled in the
169 // receiving dialog
170 subjectField.setText( message.getSubject() );
171 subjectField.setEditable( false );
172
173 String body = message.getBody();
174 remove(scroll);
175 add(conversationArea, BorderLayout.CENTER);
176 conversationArea.append( body );
177 buttonPanel.remove( sendButton );
178 buttonPanel.add( replyQuoteButton );
179 buttonPanel.add( replyButton );
180 buttonPanel.repaint();
181
182 receivedMessage = message;
183
184 repaint();
185 validate();
186 MessageDelegator.getInstance().showPanel( this );
187 MessageDelegator.getInstance().frontFrame( this );
188 super.receiveMessage();
189 }
190
191 public void setFrom( String from ) { this.from = from; }
192
193 /**
194 * @return the name of the tab
195 */
196 public String getPanelName()
197 {
198 String to = toField.getText();
199
200 //check to see if it's a private message
201 if( BuddyList.getInstance().getTabFrame() != null &&
202 BuddyList.getInstance().getTabFrame().isRoomOpen( to.replaceAll( "\\/.*", "" ) ) )
203 {
204 ChatRoomPanel window = BuddyList.getInstance().getTabFrame().getChatPanel( to.replaceAll( "\\/.*", "" ) );
205 if( window != null ) buddy = window.getBuddyStatus( to.replaceAll( "[^/]*\\/", "" ) );
206 }
207 else {
208 Roster r = ConnectorThread.getInstance().getRoster();
209 RosterEntry e = r.getEntry( toField.getText().replaceAll( "\\/.*$", "" ) );
210 if( e != null )
211 {
212 to = e.getName();
213 if( to == null || to.equals( "" ) ) to = e.getUser();
214 }
215 }
216
217 if( buddy != null && buddy instanceof MUCBuddyStatus )
218 {
219 to = buddy.getName();
220 }
221
222 if (to.length() >= 10 )
223 {
224 to = to.substring(0, 7) + "...";
225 }
226
227 if( !to.equals( "" ) )
228 {
229 return to;
230 }
231 else
232 {
233 return "message";
234 }
235 }
236
237 /**
238 * @return the name of the tab
239 */
240 public String getWindowTitle()
241 {
242 if( !toField.getText().equals( "" ) )
243 {
244 return toField.getText();
245 }
246 else
247 {
248 return "message";
249 }
250 }
251
252 /**
253 * Sets the text in the "To: " field
254 *
255 * @param to the string to set the text to
256 */
257 public void setTo( String to )
258 {
259 toField.setText( to );
260 }
261
262 /**
263 * Gets the subjectField attribute of the MessagePanel object
264 *
265 * @return The subjectField value
266 */
267 public MJTextField getSubjectField()
268 {
269 return subjectField;
270 }
271
272 /**
273 * Sets the text in the "Subject:" field
274 *
275 * @param subject the string to set the subject text to
276 */
277 public void setSubject( String subject )
278 {
279 subjectField.setText( subject );
280 }
281
282 /**
283 * Returns the MJTextArea widget
284 *
285 * @return The main text area
286 */
287 public MJTextArea getTextEntryArea()
288 {
289 return textEntryArea;
290 }
291
292 /**
293 * Called by the reply button to create a reply window
294 *
295 * @param quote if true, the message we're replying to will be included
296 * with quoted characters
297 */
298 private void replyHandler( boolean quote )
299 {
300 MessagePanel window = new MessagePanel();
301 window.setFrom( from );
302 window.setTo( toField.getText() );
303 window.setSubject( "Re: " + subjectField.getText() );
304 window.validate();
305 if( quote == true )
306 {
307 window.getTextEntryArea().setText( quoteMessage( receivedMessage.getBody(), QUOTE_STRING ) );
308 }
309 MessageDelegator.getInstance().showPanel( window );
310 MessageDelegator.getInstance().frontFrame( window );
311 window.getTextEntryArea().grabFocus();
312
313 closeHandler();
314 }
315
316 /**
317 * Adds the listeners to the various event emitting widgets
318 */
319 private void addListeners()
320 {
321 MessageActionListener listener = new MessageActionListener();
322 sendButton.addActionListener( listener );
323 replyButton.addActionListener( listener );
324 replyQuoteButton.addActionListener( listener );
325
326 Action closeAction =
327 new AbstractAction()
328 {
329 public void actionPerformed( ActionEvent e )
330 {
331 closeHandler();
332 }
333 };
334
335 toField.getInputMap().put( KeyStroke.getKeyStroke( KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() ), closeAction );
336 subjectField.getInputMap().put( KeyStroke.getKeyStroke( KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() ), closeAction );
337 textEntryArea.getInputMap().put( KeyStroke.getKeyStroke( KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() ), closeAction );
338 conversationArea.getInputMap().put( KeyStroke.getKeyStroke( KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() ), closeAction );
339 }
340
341 public JComponent getInputComponent()
342 {
343 JComponent comp = toField;
344
345 if( !toField.getText().equals( "" ) ) comp = subjectField;
346 if( !subjectField.getText().equals( "" ) ) comp = textEntryArea;
347 return comp;
348 }
349
350 /**
351 * Returns "quoted" string; each new line is preceded by aQuoteStr
352 *
353 * @param aMsg - String containing message to quote
354 * @param aQuoteStr - quote string
355 * @return quoted message
356 */
357 public String quoteMessage( String aMsg, String aQuoteStr )
358 {
359 String out = new String();
360 StringTokenizer strTok = new StringTokenizer( aMsg, "\n" );
361 while( strTok.hasMoreTokens() )
362 {
363 out += aQuoteStr + " " + strTok.nextToken() + "\n";
364 }
365 out += "\n";
366 return out;
367 }
368
369 /**
370 * Sends the message(s)
371 */
372 private void sendHandler()
373 {
374 if( toField.getText().equals( "" ) || textEntryArea.getText().equals( "" ) )
375 {
376 Standard.warningMessage( this, "messageWindow",
377 resources.getString( "mustSpecifyToAndBody" ) );
378 return;
379 }
380
381 // parse the list of recipients and split it using RECIPIENTS_DELIMITER character
382 // then send a message to each of them
383 StringTokenizer strTok = new StringTokenizer( toField.getText(), RECIPIENTS_DELIMITER );
384 while( strTok.hasMoreTokens() )
385 {
386 Message message = new Message();
387
388 // sets up the message
389 message.setBody( textEntryArea.getText() );
390 message.setType( Message.Type.NORMAL );
391 message.setSubject( subjectField.getText() );
392 message.setFrom( from );
393 message.setTo( strTok.nextToken().trim() );
394 // make sure to remove unnecessary spaces around the JID
395
396 BuddyList.getInstance().getConnection().sendPacket( message );
397 }
398 closeHandler();
399 }
400
401
402 /**
403 * Handles the events in the MessageDialog
404 *
405 * @author Adam Olsen
406 * @created March 2, 2005
407 * @version 1.0
408 */
409 class MessageActionListener implements ActionListener
410 {
411 /**
412 * called by the button widgets
413 *
414 * @param e Description of the Parameter
415 */
416 public void actionPerformed( ActionEvent e )
417 {
418 if( e.getSource() == sendButton )
419 {
420 sendHandler();
421 }
422 if( e.getSource() == replyButton )
423 {
424 replyHandler( false );
425 }
426 if( e.getSource() == replyQuoteButton )
427 {
428 replyHandler( true );
429 }
430 }
431 }
432 }
433