Files
LocalChatApp/src/client/view/main/GroupListItem.java
T
2026-02-08 23:58:00 +08:00

214 lines
6.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package client.view.main;
import client.service.LocalData;
import client.view.MainPage;
import client.view.util.CircleCharIcon2;
import client.view.util.DesignToken;
import client.view.util.RoundedRectCharIcon;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
// 群聊列表项组件
public class GroupListItem extends JPanel implements Comparable<String> {
private int unread;
private final String groupId;
JLabel icon;
JLabel badge;
JPanel centerPanel;
JLabel titleLabel;
JPanel rightPanel; // 用于放置徽章
/**
* 构造函数
*
* @param groupId 群聊ID
* @param title 群聊标题
* @param unread 未读消息数量
*/
public GroupListItem(String groupId, String title, int unread) {
this.groupId = groupId;
this.unread = unread;
// 设置布局管理器
setLayout(new BorderLayout(10, 0));
setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));
setMaximumSize(new Dimension(Integer.MAX_VALUE, 70));
setPreferredSize(new Dimension(200, 70));
// 左侧图标
boolean isGroup = LocalData.get().getGroupData(groupId) != null;
if (isGroup) {
icon = new JLabel(new RoundedRectCharIcon(Color.decode(DesignToken.BUBBLE_COLOR_BLUE), Color.WHITE,
title.substring(0, 1).toUpperCase(), 40));
} else {
icon = new JLabel(new CircleCharIcon2(Color.ORANGE, Color.WHITE,
title.substring(0, 1).toUpperCase(), 40));
}
icon.setPreferredSize(new Dimension(40, 40));
// 中间区域 - 群聊标题
centerPanel = new JPanel(new GridLayout(1, 1));
titleLabel = new JLabel(title);
titleLabel.setFont(new Font(DesignToken.DEFAULT_FONT, Font.BOLD, 14));
centerPanel.add(titleLabel);
// 右侧区域 - 未读消息徽章
rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
rightPanel.setOpaque(false);
badge = new JLabel();
badge.setForeground(Color.WHITE);
badge.setBackground(Color.RED);
badge.setOpaque(true);
badge.setHorizontalAlignment(SwingConstants.CENTER);
badge.setFont(new Font("Microsoft YaHei", Font.BOLD, 10));
badge.setBorder(BorderFactory.createEmptyBorder(2, 6, 2, 6));
badge.setPreferredSize(new Dimension(20, 20));
updateBadge(); // 初始化徽章显示状态
rightPanel.add(badge);
// 组装
this.add(icon, BorderLayout.WEST);
this.add(centerPanel, BorderLayout.CENTER);
this.add(rightPanel, BorderLayout.EAST);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
enterGroup();
}
@Override
public void mouseEntered(MouseEvent e) {
setBackground(new Color(240, 240, 240)); // 悬停效果
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(UIManager.getColor("Panel.background")); // 恢复原背景
}
@Override
public void mousePressed(MouseEvent e) {
setBackground(new Color(220, 220, 220)); // 点击效果
}
@Override
public void mouseReleased(MouseEvent e) {
if (contains(e.getPoint())) {
setBackground(new Color(240, 240, 240));
} else {
setBackground(UIManager.getColor("Panel.background"));
}
}
});
}
/**
* 更新徽章显示
*/
private void updateBadge() {
if (unread > 0) {
String badgeText = unread > 99 ? "99+" : String.valueOf(unread);
badge.setText(badgeText);
badge.setVisible(true);
// 根据文本长度调整徽章大小
FontMetrics fm = badge.getFontMetrics(badge.getFont());
int width = fm.stringWidth(badgeText) + 12;
badge.setPreferredSize(new Dimension(width, 20));
} else {
badge.setVisible(false);
}
}
/**
* 更新组件
* 将组件上对应的信息修改。
* newUnread 是加在原有的unread上的
*/
public void updateUI(String name, int newUnread) {
titleLabel.setText(name);
// 更新图标的首字母显示
boolean isGroup = LocalData.get().getGroupData(groupId) != null;
if (isGroup) {
icon.setIcon(new RoundedRectCharIcon(Color.decode(DesignToken.BUBBLE_COLOR_BLUE), Color.WHITE,
name.substring(0, 1).toUpperCase(), 40));
} else {
icon.setIcon(new CircleCharIcon2(Color.ORANGE, Color.WHITE,
name.substring(0, 1).toUpperCase(), 40));
}
unread += newUnread;
updateBadge();
}
/**
* 点击事件
* 当点击之后,使用UIUpdater来更新ContentView的UI
* 使得其加载新的群聊信息
* 清空unread为0
* UIUpdater在ContentView展示当前群聊信息的时候不会更新这个群聊的未读信息数量。
*/
public void enterGroup() {
unread = 0;
LocalData.get().setCurrentChatId(groupId);
updateBadge(); // 更新徽章显示
String name;
if (LocalData.get().getFriends().containsKey(groupId)) {
name = LocalData.get().getFriends().get(groupId);
} else {
name = LocalData.get().getGroupName(groupId);
}
updateUI(name, 0);
MainPage.get().exchangeToChatRoom(groupId);
if (LocalData.get().getGroupData(groupId) != null) {
System.out.println(
"进入群聊:" + groupId +
",人数:" + LocalData.get().getGroupData(groupId).getMemberCount() +
", 信息数量: " + LocalData.get().getChatMsg(groupId).size());
} else {
System.out.println("进入私聊:" + groupId);
}
MainPage.get().revalidate(); // 重新计算布局
MainPage.get().repaint();
}
/**
* 获取未读消息数量
*/
public int getUnread() {
return unread;
}
/**
* 获取群组ID
*/
public String getGroupId() {
return groupId;
}
/**
* 实现Comparable接口,用于排序
* 按照群组ID进行排序
*
* @param o 要比较的对象
* @return 比较结果
*/
@Override
public int compareTo(String o) {
return this.groupId.compareTo(o);
}
}