📄 buddytree.java
字号:
/* * @(#)BuddyTree.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: BuddyTree.java,v 1.21 2004/08/04 07:05:49 xrath Exp $ */package rath.jmsn;import java.awt.*;import java.awt.dnd.*;import java.awt.datatransfer.*;import java.awt.event.*;import java.io.IOException;import java.util.Date;import java.util.Hashtable;import java.util.Iterator;import java.util.Vector;import java.util.Enumeration;import java.util.Properties;import javax.swing.*;import javax.swing.tree.*;import javax.swing.event.*;import rath.msnm.*;import rath.msnm.entity.MsnFriend;import rath.msnm.entity.Group;import rath.msnm.event.*;import rath.msnm.msg.*;import rath.msnm.ftp.VolatileDownloader;import rath.msnm.ftp.VolatileTransferServer;import rath.jmsn.ui.ChatDialog;import rath.jmsn.entity.FileItem;import rath.jmsn.util.Msg;import rath.jmsn.util.MusicBox;import rath.jmsn.util.BuddyComparator;import rath.jmsn.util.UserStatusBox;/** * * @author Jang-Ho Hwang, rath@linuxkorea.co.kr * @version $Id: BuddyTree.java,v 1.21 2004/08/04 07:05:49 xrath Exp $ */public class BuddyTree extends JTree implements DragSourceListener, DragGestureListener, DropTargetListener, TreeExpansionListener{ private MsnFriend me = null; private MSNMessenger msnm = null; private MainFrame main = null; private Image chatIcon = null; private DefaultTreeModel model = null; private DefaultMutableTreeNode root = null; private MouseAdapter treeMouseAdapter = new BuddyMouseAdapter(); private int inboxUnread = -1; /** * Determine offline buddy has shown. */ private boolean offView = true; /** * key is Group Index, value is MutableTreeNode. */ private Hashtable groupMap = new Hashtable(); /** * User's loginName or connected session id is key, * and related ChatDialog is value. */ private Hashtable sessionMap = new Hashtable(); /** * Pre-creation dialog table, * Key is target user's LoginName, * Value is specify ChatDialog instance. * <p> * When you attempt to connect other new user, the value will put. * When who joined and exists in dialogMap, remove that and * notify value(dialog). * Then current session set to found dialog, maybe queue flushed! */ private Hashtable dialogMap = new Hashtable(); private DragSource dragSource = new DragSource(); /** * buddyListModified 捞亥飘 荐脚懔, syncAllUsers 皋家靛甫 龋免窍瘤 臼阑 * 冉荐甫 历厘茄促. 扁夯蔼档 0 捞绊, 焊烹 鞘夸且 版快 1阑 措涝窍瘤父, * 2-3俺狼 皋矫瘤甫 悼矫俊 焊尘锭绰 2唱 3阑 措涝窍搁 瓤苞利捞促. */ private int nonUpdateCount = 0; private Hashtable expandGroupMap = new Hashtable(); private Image backImage = null; private BuddyComparator comparator = new BuddyComparator(); public BuddyRenderer renderer = new BuddyRenderer(); public BuddyTree( MainFrame m ) { this.main = m; this.msnm = m.getMessenger(); msnm.addMsnListener( new Listener() ); ToolTipManager.sharedInstance().registerComponent(this); setBackground( Color.white ); setCellRenderer( renderer ); addTreeExpansionListener( this ); addMouseListener( treeMouseAdapter ); addKeyListener( new KeyAdapter() { public void keyPressed( KeyEvent e ) { if( e.getKeyCode()==KeyEvent.VK_ENTER ) { DefaultMutableTreeNode o = (DefaultMutableTreeNode)getLastSelectedPathComponent(); if( o==null ) return; Object uo = o.getUserObject(); if( uo instanceof MsnFriend && o!=root ) { MsnFriend friend = (MsnFriend)uo; createNewSession( friend ); } } } }); getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ); dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY_OR_MOVE, this ); new DropTarget( this, this ); chatIcon = new ImageIcon( getClass().getResource("/resources/icon/chat.jpg") ).getImage(); setOpaque( false ); } public void setMyPhoto( Image image ) { for(Iterator i=dialogMap.values().iterator(); i.hasNext(); ) { ChatDialog cd = (ChatDialog)i.next(); cd.setMyPhoto(image); } } public void setBackgroundImage( Image image ) { if( backImage!=null ) backImage.flush(); this.backImage = image; repaint(); } public Image getBackgroundImage() { return this.backImage; } /** * Enable to view LoginName. */ public String getToolTipText( MouseEvent e ) { Point p = e.getPoint(); TreePath path = getPathForLocation(p.x, p.y); if( path==null ) return null; DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); Object obj = node.getUserObject(); if( obj!=null && obj instanceof MsnFriend ) { MsnFriend friend = (MsnFriend)obj; if( friend.getLoginName().equals( me.getLoginName() ) ) return this.inboxUnread==-1?friend.getLoginName():Msg.get("label.inboxunread")+" : "+this.inboxUnread; else return friend.getLoginName(); } return null; } /** * 肺弊牢捞 肯丰登菌阑锭 秦具瞪 老甸阑 荐青茄促. * 磊扁 磊脚阑 Root node肺 积己窍绊, Model阑 货肺 积己窍绰 殿狼 累诀阑 荐青茄促. * */ public void start( MsnFriend i ) { this.me = i; this.me.setStatus( msnm.getInitialStatus() ); this.me.setGroupIndex( -1 ); this.root = new DefaultMutableTreeNode(me); this.model = new DefaultTreeModel( root ); setModel( model ); expandRow( 0 ); renderer.forward = msnm.getBuddyGroup().getForwardList(); renderer.block = msnm.getBuddyGroup().getBlockList(); syncAllUsers(); } /** * 捞 皋家靛绰 阿 弊缝狼 Expand 惑怕甫 Monitoring 窍绰 捞亥飘 府胶呈捞促. * Expandsion event啊 惯积茄 node啊 Group 牢胶畔胶捞搁 Map捞 持绢敌促. * * @param e */ public void treeCollapsed( TreeExpansionEvent e ) { TreePath path = e.getPath(); DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); Object o = node.getUserObject(); if( o instanceof Group ) { Group group = (Group)o; expandGroupMap.remove( group.getIndex() ); } } /** * 捞 皋家靛绰 阿 弊缝狼 Expand 惑怕甫 Monitoring 窍绰 捞亥飘 府胶呈捞促. * Expandsion event啊 惯积茄 node啊 Group 牢胶畔胶捞搁 Map俊辑 力芭茄促. * * @param e */ public void treeExpanded( TreeExpansionEvent e ) { TreePath path = e.getPath(); DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); Object o = node.getUserObject(); if( o instanceof Group ) { Group group = (Group)o; expandGroupMap.put( group.getIndex(), path ); } } protected DefaultMutableTreeNode findGroupNode( Integer groupIndex ) { return (DefaultMutableTreeNode)groupMap.get(groupIndex); } /** * 葛电 child甸阑 力芭茄饶, ForwardList俊 乐绰 葛电 荤侩磊甸阑 * Root node俊 老褒 火涝茄促. * * 措脚 弊缝 府胶飘肺 唱鸥唱霸 等促. (公炼扒 弊缝捞促) * 捞 皋家靛啊 荐青窍绰 老阑 唱鸥郴焊磊. * <p> * <ul> * <li>Root node狼 葛电 弊缝甸苞 children阑 力芭茄促. * <li>GroupList肺何磐 弊缝 TreeNode甸阑 眠啊茄促. * <li>阿 Buddy甸阑 棵官弗 group treenode俊 眠啊茄促. * </ul> */ void syncAllUsers() { if( root==null || model==null ) return; root.removeAllChildren(); for(Iterator i=groupMap.values().iterator(); i.hasNext(); ) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)i.next(); node.removeAllChildren(); } groupMap.clear(); GroupList gl = msnm.getBuddyGroup().getGroupList(); gl.sort(); for(Iterator i=gl.iterator(); i.hasNext(); ) { Group group = (Group)i.next(); DefaultMutableTreeNode node = new DefaultMutableTreeNode(group); root.add( node ); groupMap.put( group.getIndex(), node ); } BuddyList bl = msnm.getBuddyGroup().getForwardList(); bl.sort(comparator); for(Iterator i=bl.iterator(); i.hasNext(); ) { MsnFriend friend = (MsnFriend)i.next(); if( !offView && friend.getStatus().equals(UserStatus.OFFLINE) ) continue; DefaultMutableTreeNode node = findGroupNode( friend.getGroupIndex() ); DefaultMutableTreeNode fnode = new DefaultMutableTreeNode(friend); node.add( fnode ); } model.reload(); recoverExpandState(); } /** * 捞傈惑怕狼 Group node甸狼 expand惑怕甫 葛滴 雀汗茄促. */ private void recoverExpandState() { int rowIndex = 0; while( rowIndex < getRowCount() ) { TreePath path = getPathForRow(rowIndex++); if( path.getPathCount()==2 ) // Is Group Node Path? { Group group = (Group)((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); if( expandGroupMap.containsKey(group.getIndex()) ) expandPath( path ); } } } /** * 泅犁 Tree俊辑 林绢柳 friend啊 困摹茄 Node甫 茫酒 馆券茄促. * 父距 粮犁窍瘤 臼绰促搁 null阑 馆券且 巴捞促. */ protected DefaultMutableTreeNode findTreeNode( MsnFriend friend ) { for(Enumeration e = root.children();e.hasMoreElements();) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); for(Enumeration e1 = node.children(); e1.hasMoreElements(); ) { DefaultMutableTreeNode fnode = (DefaultMutableTreeNode)e1.nextElement(); if( fnode.getUserObject().equals(friend) ) return fnode; } } return null; } /** * toInsert 模备甫 Group俊 眠啊窍妨绊 且锭, 沥纺鉴辑惑 棵官弗 GroupNode郴狼 Index甫 * 拌魂秦霖促. * * @param groupNode 火涝且 Group Node * @param toInsert 火涝瞪 MsnFriend 按眉. * @param node MsnFriend按眉甫 UserObject肺 啊瘤绰 DefaultMutableTreeNode * @return */ protected int insertPreferredIndex( DefaultMutableTreeNode groupNode, MsnFriend toInsert, DefaultMutableTreeNode toAdd ) { int index = 0; for(Enumeration e=groupNode.children(); e.hasMoreElements(); ) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); MsnFriend friend = (MsnFriend)node.getUserObject(); // 霉锅掳 颇扼固磐啊 困肺 棵扼啊妨搁 澜荐啊 馆券登绢具 茄促. // 弊府绊 惑怕函版矫, 公炼扒 remove窍绊, 捞 皋家靛甫 烹秦辑 促矫 add登具且 巴捞促. if( comparator.compare(friend, toInsert) > 0 ) { groupNode.insert( toAdd, index ); return index; } index++; } groupNode.add( toAdd ); return index; } /** * 荤侩磊俊霸 富阑 吧锭 荤侩茄促. * * Old implementation: <p> * 秦寸 模备客 楷搬等 技记捞 乐绰瘤 茫酒夯 饶, * 捞固 肝绢柳 技记捞 绝促搁, 悼扁皋家靛 doCallWait栏肺 技记阑 楷搬茄促. * 父距 技记捞 楷搬登瘤 臼疽促搁, 梆官肺 return窍哥, * 技记阑 茫疽芭唱 货肺 肝绰单 己傍窍看促搁, sessionMap(促捞倔肺弊 焊包甘)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -