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