📄 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.18 2002/08/24 15:54:36 pistos 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.18 2002/08/24 15:54:36 pistos 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 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 )
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -