📄 clusterimcontainer.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.ui;
import static edu.tsinghua.lumaqq.resource.Messages.*;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import edu.tsinghua.lumaqq.ecore.face.Face;
import edu.tsinghua.lumaqq.events.IFaceSelectionListener;
import edu.tsinghua.lumaqq.models.Cluster;
import edu.tsinghua.lumaqq.models.ClusterType;
import edu.tsinghua.lumaqq.models.GroupType;
import edu.tsinghua.lumaqq.models.Model;
import edu.tsinghua.lumaqq.models.ModelRegistry;
import edu.tsinghua.lumaqq.models.User;
import edu.tsinghua.lumaqq.qq.beans.ClusterIM;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.in.ClusterCommandReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.record.IKeyConstants;
import edu.tsinghua.lumaqq.record.RecordEntry;
import edu.tsinghua.lumaqq.resource.Colors;
import edu.tsinghua.lumaqq.resource.DefaultFace;
import edu.tsinghua.lumaqq.resource.Resources;
import edu.tsinghua.lumaqq.ui.config.user.UserInfoWindow;
import edu.tsinghua.lumaqq.ui.helper.DateTool;
import edu.tsinghua.lumaqq.ui.helper.FaceRegistry;
import edu.tsinghua.lumaqq.ui.provider.ClusterMemberLabelProvider;
import edu.tsinghua.lumaqq.ui.provider.MapValueContentProvider;
import edu.tsinghua.lumaqq.ui.sorter.ModelSorter;
import edu.tsinghua.lumaqq.widgets.FaceImageAdvisor;
import edu.tsinghua.lumaqq.widgets.IImageSelectorAdvisor;
import edu.tsinghua.lumaqq.widgets.ImageSelector;
import edu.tsinghua.lumaqq.widgets.rich.IRichContent;
import edu.tsinghua.lumaqq.widgets.rich.LineStyle;
import edu.tsinghua.lumaqq.widgets.rich.RichBox;
/**
* 群聊天容器
*
* @author luma
*/
public class ClusterIMContainer extends Composite implements IIMContainer, IFaceSelectionListener, IIMSender {
//设置输入框为可输入
private Runnable enableRunnable = new Runnable() {
public void run() {
if(inputBox.isDisposed())
return;
inputBox.setReadonly(false);
inputBox.setBackground(Colors.WHITE);
}
};
/**
* 往输出框追加提示信息
*
* @author luma
*/
private class AppendRunnable implements Runnable {
public String hint;
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
if(inputBox.isDisposed())
return;
appendHint('\n' + hint + "\n\n", hintStyle);
}
}
private Resources res;
private MainShell main;
private IContainerKeyHandler keyHandler;
private int unread;
private boolean active;
private Cluster cluster;
// 消息流程封装类
private ClusterIMDelegate workflow;
private AppendRunnable appendRunnable;
private CLabel lblName;
private CLabel lblList;
private RichBox outputBox, inputBox;
private Composite sideContainer, chatContainer, noticeContainer;
private TableViewer listViewer;
private Sash vSash;
private Text textNotice;
private ToolBar infoBar;
private Menu memberMenu;
// style样式表缓冲区
private List<LineStyle> styleCache;
// 提示信息的样式
private static final LineStyle hintStyle = new LineStyle(null, null, "宋体", SWT.NORMAL, 9);
// 缺省的用户名称提示样式
private static final LineStyle myStyle = new LineStyle(Colors.MY_HINT_COLOR, null, "宋体", SWT.NORMAL, 9);
private static final LineStyle otherStyle = new LineStyle(Colors.BLUE, null, "宋体", SWT.NORMAL, 9);
private ViewForm inputForm, infoForm;
// true表示群栏目收起
private boolean infoFormExpanded;
// 关闭窗口action
private Runnable closeAction = new Runnable() {
public void run() {
if(keyHandler != null)
keyHandler.onKeyDown(SWT.MOD3, 'C');
}
};
// 查看记录的action
private Runnable showRecordAction = new Runnable() {
public void run() {
if(keyHandler != null)
keyHandler.onKeyDown(SWT.MOD3, 'H');
}
};
// 发送消息的action
private Runnable sendAction = new Runnable() {
public void run() {
if(!inputBox.isReadonly())
send();
}
};
// 切换下一个未读tab
private Runnable nextUnreadTabAction = new Runnable() {
public void run() {
if(keyHandler != null)
keyHandler.onKeyDown(SWT.MOD3, 'Q');
}
};
// 切换下一个tab
private Runnable nextTabAction = new Runnable() {
public void run() {
if(keyHandler != null)
keyHandler.onKeyDown(SWT.MOD3, SWT.ARROW_RIGHT);
}
};
// 切换上一个tab
private Runnable prevTabAction = new Runnable() {
public void run() {
if(keyHandler != null)
keyHandler.onKeyDown(SWT.MOD3, SWT.ARROW_LEFT);
}
};
// 系统平台
private static boolean IS_GTK;
private static boolean IS_MOTIF;
static {
String platform = SWT.getPlatform();
IS_GTK = "gtk".equals(platform);
IS_MOTIF = "motif".equals(platform);
}
public ClusterIMContainer(Composite parent) {
super(parent, SWT.NONE);
res = Resources.getInstance();
unread = 0;
active = false;
styleCache = new ArrayList<LineStyle>();
initLayout();
}
private void initLayout() {
GridLayout layout = new GridLayout(3, false);
layout.horizontalSpacing = layout.verticalSpacing = layout.marginHeight = layout.marginWidth = 0;
setLayout(layout);
setBackground(Colors.MAINSHELL_BACKGROUND);
// 聊天区
chatContainer = new Composite(this, SWT.NONE);
chatContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
layout = new GridLayout();
layout.marginHeight = layout.marginWidth = 1;
layout.horizontalSpacing = layout.verticalSpacing = 0;
chatContainer.setLayout(layout);
chatContainer.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
Composite c = (Composite)e.getSource();
Rectangle rect = c.getClientArea();
rect.width--;
rect.height--;
e.gc.setForeground(Colors.WIDGET_BORDER);
e.gc.drawRectangle(rect);
}
});
ViewForm outputForm = new ViewForm(chatContainer, SWT.FLAT);
outputForm.setLayoutData(new GridData(GridData.FILL_BOTH));
lblName = new CLabel(outputForm, SWT.LEFT);
lblName.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND);
lblName.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_HAND));
lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT);
lblName.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
main.getShellLauncher().openClusterInfoWindow(cluster);
}
});
lblName.addMouseTrackListener(new MouseTrackAdapter() {
public void mouseEnter(MouseEvent e) {
lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT_HOVER);
}
public void mouseExit(MouseEvent e) {
lblName.setForeground(Colors.VIEWFORM_BANNER_TEXT);
}
});
outputForm.setTopLeft(lblName);
outputBox = new RichBox(outputForm);
outputBox.setReadonly(true);
outputBox.setBackground(Colors.WHITE);
outputForm.setContent(outputBox);
Sash sash = new Sash(chatContainer, SWT.HORIZONTAL);
sash.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
sash.setBackground(Colors.READONLY_BACKGROUND);
sash.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
GridData gd = (GridData)inputForm.getLayoutData();
gd.heightHint = inputForm.getParent().getClientArea().height - e.y;
inputForm.getParent().layout();
}
});
inputForm = new ViewForm(chatContainer, SWT.FLAT);
inputForm.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 100;
inputForm.setLayoutData(gd);
final ToolBar tb = new ToolBar(inputForm, SWT.FLAT);
tb.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND);
// 字体
ToolItem tiFont = new ToolItem(tb, SWT.NONE);
tiFont.setImage(res.getImage(Resources.icoFont));
tiFont.setToolTipText(tooltip_button_font);
tiFont.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
FontDialog dialog = new FontDialog(getShell());
if(main.getDefaultStyle() != null)
dialog.setFontList(main.getDefaultStyle().createFontData());
if(main.getFontColor() != null)
dialog.setRGB(main.getFontColor().getRGB());
dialog.open();
FontData[] fontList = dialog.getFontList();
if(fontList == null) return;
RGB rgb = dialog.getRGB();
if(main.getFontColor() != null) main.getFontColor().dispose();
main.getDefaultStyle().fontName = fontList[0].getName();
main.getDefaultStyle().fontSize = fontList[0].getHeight();
main.getDefaultStyle().fontStyle = fontList[0].getStyle();
if(rgb != null) {
main.setFontColor(new Color(main.getDisplay(), rgb));
main.getDefaultStyle().foreground = main.getFontColor();
}
inputBox.setDefaultStyle(main.getDefaultStyle());
}
});
// 颜色,在有些平台下需要
if(IS_GTK || IS_MOTIF) {
ToolItem tiColor = new ToolItem(tb, SWT.NONE);
tiColor.setImage(res.getImage(Resources.icoColor));
tiColor.setToolTipText(tooltip_button_color);
tiColor.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ColorDialog dialog = new ColorDialog(getShell());
if(main.getFontColor() != null)
dialog.setRGB(main.getFontColor().getRGB());
dialog.open();
RGB rgb = dialog.getRGB();
if(rgb != null) {
if(main.getFontColor() != null)
main.getFontColor().dispose();
if(rgb != null) {
main.setFontColor(new Color(main.getDisplay(), rgb));
main.getDefaultStyle().foreground = main.getFontColor();
}
}
inputBox.setDefaultStyle(main.getDefaultStyle());
}
});
}
// 表情
ToolItem tiFace = new ToolItem(tb, SWT.NONE);
tiFace.setImage(res.getImage(Resources.icoSmiley));
tiFace.setToolTipText(tooltip_button_face);
tiFace.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Rectangle bound = tb.getBounds();
openImageSelectionShell(tb.getParent().toDisplay(bound.x, bound.y + bound.height));
}
});
// 动画状态
ToolItem tiAnimation = new ToolItem(tb, SWT.CHECK);
tiAnimation.setImage(res.getImage(Resources.icoStop));
tiAnimation.setToolTipText(tooltip_button_disable_animation);
tiAnimation.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ToolItem ti = (ToolItem)e.widget;
outputBox.setForbiddenAnimation(ti.getSelection());
inputBox.setForbiddenAnimation(ti.getSelection());
ti.setToolTipText(ti.getSelection() ? tooltip_button_animation : tooltip_button_disable_animation);
}
});
inputForm.setTopLeft(tb);
ToolBar tbSwitch = new ToolBar(inputForm, SWT.FLAT);
tbSwitch.setBackground(Colors.VIEWFORM_BANNER_BACKGROUND);
ToolItem tiSwitch = new ToolItem(tbSwitch, SWT.NONE);
tiSwitch.setImage(res.getImage(Resources.icoRightArrow));
tiSwitch.setToolTipText(tooltip_button_hide);
inputForm.setTopRight(tbSwitch);
inputBox = new RichBox(inputForm);
inputBox.setBackground(Colors.WHITE);
inputForm.setContent(inputBox);
tiSwitch.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ToolItem item = (ToolItem)e.getSource();
GridData d = (GridData)sideContainer.getLayoutData();
d.exclude = !d.exclude;
d = (GridData)vSash.getLayoutData();
d.exclude = !d.exclude;
if(d.exclude) {
sideContainer.setVisible(false);
((GridData)chatContainer.getLayoutData()).horizontalSpan = 3;
item.setImage(res.getImage(Resources.icoLeftArrow));
item.setToolTipText(tooltip_button_show);
} else {
sideContainer.setVisible(true);
((GridData)chatContainer.getLayoutData()).horizontalSpan = 1;
item.setImage(res.getImage(Resources.icoRightArrow));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -