📄 chatdialog.java
字号:
/* * @(#)ChatDialog.java * * Copyright (c) 2002, Jang-Ho Hwang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Jang-Ho Hwang nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: ChatDialog.java,v 1.38 2004/08/04 07:05:49 xrath Exp $ */package rath.jmsn.ui;import java.awt.*;import java.awt.event.*;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Enumeration;import java.util.List;import java.util.Iterator;import java.util.ArrayList;import java.util.Properties;import java.util.Vector;import java.util.Hashtable;import javax.swing.*;import javax.swing.filechooser.*;import javax.swing.text.*;import rath.msnm.UserStatus;import rath.msnm.LocalCopy;import rath.msnm.MSNMessenger;import rath.msnm.SwitchboardSession;import rath.msnm.event.MsnAdapter;import rath.msnm.entity.MsnFriend;import rath.msnm.msg.MimeMessage;import rath.msnm.msg.MimeUtility;import rath.msnm.ftp.VolatileDownloader;import rath.msnm.ftp.VolatileTransferServer;import rath.jmsn.ToolBox;import rath.jmsn.MainFrame;import rath.jmsn.NativeToolkit;import rath.jmsn.entity.FileItem;import rath.jmsn.file.FileProgress;import rath.jmsn.file.ChatLogWriter;import rath.jmsn.util.MusicBox;import rath.jmsn.util.Msg;import rath.util.HangulJamoUtil;/** * 措拳且锭 荤侩登绰 促捞倔肺弊捞促. * * @author Jang-Ho Hwang, rath@xrath.com * @version $Id: ChatDialog.java,v 1.38 2004/08/04 07:05:49 xrath Exp $ */public class ChatDialog extends JFrame implements ToolBox, DialogAppender{ private static final SimpleDateFormat ts = new SimpleDateFormat("[HH:mm]" ); private static final SimpleDateFormat sdf = new SimpleDateFormat("mm:ss"); private MSNMessenger msnm = null; private MsnFriend me = null; private JScrollPane chatPane = null; private JScrollPane inputPane = null; private JButton filesendButton = null; private ChatArea chatArea = null; private JTextArea inputArea = null; private JLabel statusLabel = null; private SwitchboardSession session = null; private boolean isSessionClose = false; private WindowListener wl = null; private JLabel photoMe = null; private JLabel photoYou = null; private JPanel photoPanel = null; private JPanel topPanel = null; private JPanel mainPanel = null; private JPanel bottomPanel = null; private MsnFriend you = null; private ArrayList queue = new ArrayList(); private ChatLogWriter log = null; private Vector fileQueue = new Vector(); private Hashtable fileCookieMap = new Hashtable(); private MsnAdapter fileAdapter = new FileAdapter(); private ArrayList historyQueue = new ArrayList(); private int historyIndex = -1; private long lastMessagingTime = 0L; private boolean isViewTimestamp = MainFrame.LOCALCOPY.getPropertyBoolean(MainFrame.TIMESTAMP_DISPLAY, false); private boolean useFixedFont = MainFrame.LOCALCOPY.getPropertyBoolean(MainFrame.USE_FIXED_CHAT_FONT, false); public ChatDialog( Frame owner, MSNMessenger msnm, String targetName, MsnFriend i ) { setTitle( targetName ); this.me = i; this.msnm = msnm; init(); } /** * 惑措规栏肺何磐 率瘤芒捞 凯啡阑锭 荤侩登绰 constructor捞促. */ public ChatDialog( Frame owner, MSNMessenger msnm, SwitchboardSession session, MsnFriend i ) { setTitle( session.getMsnFriend().getLoginName() ); this.me = i; this.you = session.getMsnFriend(); this.msnm = msnm; this.session = session; MusicBox.play( MusicBox.SOUND_MESSAGE_2 ); prepareLogWriter( you.getLoginName() ); init(); } private void init() { createComponents(); createKeyMap(); this.addComponentListener( new DialogStatus() ); super.addWindowListener( new WindowAdapter() { /** * To fix focus problem in MacOS X */ public void windowActivated( WindowEvent e ) { chatArea.requestFocus(); inputArea.requestFocus(); } }); this.msnm.addMsnListener( fileAdapter ); Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); int x = (int)(Math.random() * (double)(size.height-getSize().width)); int y = (int)(Math.random() * (double)(size.height-getSize().height)); setLocation( x, y ); setDefaultCloseOperation( DISPOSE_ON_CLOSE ); } private void prepareLogWriter( String targetName ) { if( this.log!=null ) return; String logdir = msnm.getLocalCopy().getProperty( MainFrame.CHATLOG_PROP ); File file = new File( logdir, targetName + ".txt" ); try { this.log = new ChatLogWriter( file ); } catch( IOException e ) { System.err.println( "can't write log file." ); } } private class FileAdapter extends MsnAdapter { public void fileReceiveStarted( VolatileDownloader down ) { String cookie = down.getCookie(); FileProgress prog = null; if( (prog=(FileProgress)fileCookieMap.remove(cookie))!=null ) { prog.setTransfer( down ); } } public void fileSendStarted( VolatileTransferServer vts ) { String cookie = vts.getCookie(); FileProgress prog = null; if( (prog=(FileProgress)fileCookieMap.remove(cookie))!=null ) { prog.setTransfer( vts ); } } public void fileSendError( VolatileTransferServer server, Throwable e ) { e.printStackTrace(); } public void fileSendAccepted( SwitchboardSession ss, int cookie ) { if( session==null ) return; if( ss.getSessionId().equals( session.getSessionId() ) ) { final FileProgress prog = new FileProgress( ChatDialog.this ); fileCookieMap.put( String.valueOf(cookie), prog ); SwingUtilities.invokeLater( new Runnable() { public void run() { topPanel.add( prog ); topPanel.doLayout(); topPanel.validate(); } }); MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.filesend.accept", you.getLoginName()) ); appendMessage( msg ); } } public void fileSendRejected( SwitchboardSession ss, int cookie, String reason ) { if( session==null ) return; if( ss.getSessionId().equals( session.getSessionId() ) ) { MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.filesend.reject", you.getLoginName()) ); appendMessage( msg ); } } } public void addFileItem( final FileItem item ) { fileQueue.add(item); MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.filerecv.notify", you.getFormattedFriendlyName(), item.getName()+"("+item.getKBSize()+")") ); appendMessage( msg ); if( Boolean.getBoolean("jmsn.file.auto.accept") ) acceptFileRequest(); } private void createKeyMap() { JPanel panel = (JPanel)getContentPane(); ComponentInputMap im = new ComponentInputMap(panel); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK), "FileAccept" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK), "FileAccept" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK), "FileReject" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK), "FileReject" ); ActionMap am = panel.getActionMap(); am.put( "FileAccept", new AbstractAction() { public void actionPerformed( ActionEvent e ) { acceptFileRequest(); } }); am.put( "FileReject", new AbstractAction() { public void actionPerformed( ActionEvent e ) { if( fileQueue.size()==0 ) return; FileItem item = (FileItem)fileQueue.remove(0); SwitchboardSession ss = item.getSession(); try { ss.rejectFileReceive( item.getCookie() ); } catch( IOException ex ) { ex.printStackTrace(); } MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.filerecv.reject") ); appendMessage( msg ); } }); panel.setInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW, im ); addKeyListener( new KeyAdapter() { public void keyPressed( KeyEvent e ) { if( e.getKeyCode()==KeyEvent.VK_ESCAPE ) dispose(); } }); } private class DialogStatus extends ComponentAdapter { /* public void componentShown( ComponentEvent e ) { inputArea.requestFocus(); ChatDialog.this.show(); } */ public void componentResized( ComponentEvent e ) { chatPane.getViewport().scrollRectToVisible( new Rectangle(0, chatArea.getSize().height, 100, 100) ); } } private void acceptFileRequest() { if( fileQueue.size()==0 ) return; FileItem item = (FileItem)fileQueue.remove(0); SwitchboardSession ss = item.getSession(); LocalCopy local = msnm.getLocalCopy(); FileProgress prog = new FileProgress(this); try { File file = new File( local.getProperty(MainFrame.DOWNLOAD_PROP), item.getName() ); fileCookieMap.put( String.valueOf(item.getCookie()), prog ); ss.acceptFileReceive( item.getCookie(), file ); } catch( IOException ex ) { ex.printStackTrace(); } topPanel.add( prog ); topPanel.doLayout(); topPanel.validate(); } public void sessionClosed() { this.session = null; isSessionClose = true; } public void userOffline() { if( you==null ) return; MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.msg.offline", you.getLoginName()) ); appendMessage( msg ); filesendButton.setEnabled( false ); inputArea.setEnabled( false ); //chatArea.requestFocus(); } public void setMyPhoto( Image img ) { if( img==null ) { photoMe.setIcon( null ); bottomPanel.remove( photoMe ); bottomPanel.doLayout(); bottomPanel.validate(); } else { photoMe.setIcon( new ImageIcon(img) ); bottomPanel.add( photoMe, "East" ); bottomPanel.doLayout(); bottomPanel.validate(); } } public void setFriendPhoto( Image img ) { boolean isShow = MainFrame.LOCALCOPY.getPropertyBoolean(MainFrame.PHOTO_PROP_SHOW, true); if( !isShow || img==null ) { photoYou.setIcon( null ); mainPanel.remove( photoPanel ); mainPanel.doLayout(); mainPanel.validate(); } else { photoYou.setIcon( new ImageIcon(img) ); mainPanel.add( photoPanel, "East" ); mainPanel.doLayout(); mainPanel.validate(); } } private void createComponents() { setSize( 380, 370 ); JPanel panel = (JPanel)getContentPane(); chatArea = new ChatArea() { public void acceptFiles( List list ) { for(Iterator i=list.iterator(); i.hasNext(); ) sendFileImpl( (File)i.next() ); } public void inviteFriend( String loginName ) { if( session!=null ) { try { session.inviteFriend( loginName ); MimeMessage msg = new MimeMessage(); msg.setMessage( Msg.get("chatdlg.msg.invite", loginName) ); appendMessage( msg ); } catch( IOException e ) {} } } }; chatArea.setFont( FONT_10 ); chatArea.append( Msg.get("chatdlg.msg.top") ); JPanel propertyPane = new JPanel(); propertyPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2)); JButton fontButton = new JButton( Msg.get("label.font")); fontButton.setFont( FONT ); fontButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { showFontDialog(); } }); photoMe = new JLabel(); photoMe.setPreferredSize(new Dimension(98,98)); photoMe.setBorder( BorderFactory.createLineBorder(Color.black,1) ); photoYou = new JLabel(); photoYou.setPreferredSize(new Dimension(98,98)); photoYou.setBorder( BorderFactory.createLineBorder(Color.black,1) ); photoPanel = new JPanel(new BorderLayout()); photoPanel.add( new JPanel(), "Center" ); photoPanel.add( photoYou, "North" ); propertyPane.add(fontButton); inputArea = new JTextArea(); inputArea.setFont( FONT_10 ); inputArea.setLineWrap( true ); statusLabel = new JLabel(""); statusLabel.setFont( FONT_10 ); statusLabel.setPreferredSize( new Dimension(100, 24) ); chatPane = new JScrollPane( chatArea); inputPane = new JScrollPane( inputArea ); inputPane.setPreferredSize( new Dimension(100, 50) ); bottomPanel = new JPanel(new BorderLayout()); JPanel southPanel = new JPanel(new BorderLayout()); southPanel.add( propertyPane, "North"); southPanel.add( inputPane, "Center" ); southPanel.add( statusLabel, "South" ); bottomPanel.add( southPanel, "Center" ); topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 4)); topPanel.setPreferredSize( new Dimension(100,38) ); topPanel.setBorder( BorderFactory.createEtchedBorder() ); filesendButton = new JButton(Msg.get("button.file.send")); filesendButton.setFont( FONT ); filesendButton.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { prepareSendFile(); } }); topPanel.add( filesendButton ); mainPanel = new JPanel(new BorderLayout()); mainPanel.add( chatPane, "Center" ); panel.add( topPanel, "North" ); panel.add( mainPanel, "Center" ); panel.add( bottomPanel, "South" ); InputMap im = inputArea.getInputMap(); ActionMap am = inputArea.getActionMap(); AbstractAction newlineAction = new AbstractAction() { public void actionPerformed( ActionEvent e ) { inputArea.append("\n"); } }; im.put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_MASK), "newline" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK), "newline" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "send" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.ALT_MASK), "TopMost" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "HistoryUp" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD8, 0), "HistoryUp" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "HistoryDown" ); im.put( KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD2, 0), "HistoryDown" ); am.put( "newline", newlineAction ); am.put( "send", new AbstractAction() { public void actionPerformed( ActionEvent e ) { sendMessage(); } }); am.put( "dispose", new AbstractAction() { public void actionPerformed( ActionEvent e ) { dispose(); } }); am.put( "TopMost", new AbstractAction() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -