📄 recordviewer.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.widgets;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
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.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import edu.tsinghua.lumaqq.IMessage;
import edu.tsinghua.lumaqq.IconHolder;
import edu.tsinghua.lumaqq.LumaQQ;
import edu.tsinghua.lumaqq.MessageEntry;
import edu.tsinghua.lumaqq.qq.Utils;
/**
* 聊天记录查看器控件,做成控件比较方便维护
*
* @author 马若劼
*/
public class RecordViewer extends Composite implements DisposeListener {
// 在表的大小改变时,修改表头的宽度
private class ResizeListener extends ControlAdapter {
// 保存宽度的数值,-1表示占据所有未用部分
private int[] width;
// 表示宽度的数值是否是个相对量
private boolean[] relative;
// 构造函数
public ResizeListener(String[] w) {
setWidth(w);
}
public void controlResized(ControlEvent e) {
// 得到表的客户区大小
Table table = (Table)e.getSource();
int caWidth = table.getClientArea().width;
// 已分配的宽度
int allocWidth = 0;
// 临时变量
int w;
// 先设置width不等于-1的行
for(int i = 0; i < width.length; i++) {
if(width[i] != -1) {
TableColumn tc = table.getColumn(i);
w = relative[i] ? (caWidth * width[i] / 100) : width[i];
allocWidth += w;
tc.setWidth(w);
}
}
// 再设置宽度为-1,也就是占据剩余空间的行,如果有多个-1的行,则只有第一个可以显示,其他的
// 都会被置为0
for(int i = 0; i < width.length; i++) {
if(width[i] == -1) {
TableColumn tc = table.getColumn(i);
w = caWidth - allocWidth;
allocWidth += w;
tc.setWidth(w);
}
}
}
/**
* 根据输入的字符串形式的宽度描述,转换成内部描述,这样是为了避免每次都解析字符串
* @param w
*/
public void setWidth(String[] w) {
width = new int[w.length];
relative = new boolean[w.length];
for(int i = 0; i < w.length; i++) {
relative[i] = w[i].endsWith("%");
if(w[i].equals("*"))
width[i] = -1;
else
width[i] = Utils.getInt(w[i].substring(0,
relative[i] ? (w[i].length() - 1) : w[i].length()), 10);
}
}
}
// Log对象
private static Log log = LogFactory.getLog(RecordViewer.class);
// 界面控件
private Label lblYear, lblMonth, lblDay;
private Button chkDisplayAll;
private Table recordTable;
private Menu recordMenu;
// 年月日
private int year, month, day;
// 消息管理器
private IMessage mm;
// TableItem字符串格式化器
private IRecordFormatter formatter;
private IRecordExporter exporter;
// TableItem选择事件监听器
private List listeners;
// IconHolder实例
private IconHolder icons;
// 剪贴板实例
private Clipboard clipboard;
// QQ号,表示这个RecordViewer用于查看与哪个好友的聊天记录,10000表示系统消息
private int qqNum;
// 表resiz事件处理器
private ResizeListener rl;
/**
* @param parent
* @param style
*/
public RecordViewer(Composite parent, int style) {
super(parent, style);
// 初始化变量
listeners = new ArrayList();
clipboard = new Clipboard(getDisplay());
icons = IconHolder.getInstance();
Calendar c = Calendar.getInstance();
year = c.get(Calendar.YEAR);
month = c.get(Calendar.MONTH) + 1;
day = c.get(Calendar.DAY_OF_MONTH);
// 初始化窗口布局
initLayout();
// 初始化弹出菜单
initPopupMenu();
// 添加事件监听器
addDisposeListener(this);
}
/**
* 初始化弹出菜单
*/
private void initPopupMenu() {
recordMenu = new Menu(this);
// 拷贝消息到剪贴板
MenuItem mi = new MenuItem(recordMenu, SWT.PUSH);
mi.setText(LumaQQ.getResourceString("record.viewer.menu.copy"));
mi.setImage(icons.getResource(IconHolder.icoCopy));
mi.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
int index = recordTable.getSelectionIndex();
if(index != -1) {
MessageEntry me = (MessageEntry)recordTable.getItem(index).getData();
String copyString = formatter.copy(me);
if(copyString != null)
clipboard.setContents(new Object[] { copyString }, new Transfer[] { TextTransfer.getInstance() });
}
}
}
);
// 导出表中所有信息
mi = new MenuItem(recordMenu, SWT.PUSH);
mi.setText(LumaQQ.getResourceString("record.viewer.menu.export"));
mi.setImage(icons.getResource(IconHolder.icoTxtFile));
mi.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// 创建文件对话框,设置参数,打开
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setFilterExtensions(new String[] { "*.txt", "*.*" } );
dialog.setFileName(String.valueOf(qqNum) + ".txt");
String filename = dialog.open();
// 如果filename不等于null则导出
if(filename != null) {
BufferedWriter writer = null;
try {
// 创建文本文件
File file = new File(filename);
if(!file.exists())
file.createNewFile();
// 创建流
writer = new BufferedWriter(new FileWriter(file));
// 导出头部
writer.write(exporter.exportHeader());
// 得到TableItem总数,然后得到TableItem,交给exporter处理
int size = recordTable.getItemCount();
for(int i = 0; i < size; i++) {
writer.write(exporter.exportString((MessageEntry)recordTable.getItem(i).getData()));
}
writer.flush();
} catch (IOException ex) {
log.error("保存聊天记录到文本文件失败");
} finally {
try {
if(writer != null)
writer.close();
} catch (IOException e1) {
}
}
}
}
}
);
// 添加菜单显示事件监听器
recordMenu.addMenuListener(
new MenuAdapter() {
public void menuShown(MenuEvent e) {
recordMenu.getItem(0).setEnabled(recordTable.getSelectionIndex() != -1);
}
}
);
}
/**
* 初始化界面布局
*/
private void initLayout() {
setLayout(new FormLayout());
// 显示标签
Label lblDisplay = new Label(this, SWT.NONE);
lblDisplay.setText(LumaQQ.getResourceString("record.viewer.label.display"));
FormData fd = new FormData();
fd.left = new FormAttachment(0, 0);
fd.top = new FormAttachment(0, 0);
lblDisplay.setLayoutData(fd);
// 年标签
lblYear = new Label(this, SWT.LEFT);
lblYear.setText(String.valueOf(year));
fd = new FormData();
fd.left = new FormAttachment(lblDisplay, 5, SWT.RIGHT);
fd.top = new FormAttachment(0, 0);
lblYear.setLayoutData(fd);
Label lblYearChar = new Label(this, SWT.NONE);
lblYearChar.setText(LumaQQ.getResourceString("record.viewer.label.year"));
fd = new FormData();
fd.left = new FormAttachment(lblYear, 0, SWT.RIGHT);
fd.top = new FormAttachment(0, 0);
lblYearChar.setLayoutData(fd);
// 调整年的上按钮
Button btnYearUp = new Button(this, SWT.ARROW | SWT.UP);
fd = new FormData();
fd.left = new FormAttachment(lblYearChar, 1, SWT.RIGHT);
fd.right = new FormAttachment(lblYearChar, 21, SWT.RIGHT);
fd.top = new FormAttachment(0, 0);
fd.bottom = new FormAttachment(0, 10);
btnYearUp.setLayoutData(fd);
btnYearUp.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if(year > 0) {
year--;
lblYear.setText(String.valueOf(year));
if(!chkDisplayAll.getSelection())
refreshRecord(false);
}
}
}
);
// 调整年的下按钮
Button btnYearDown = new Button(this, SWT.ARROW | SWT.DOWN);
fd = new FormData();
fd.left = new FormAttachment(lblYearChar, 1, SWT.RIGHT);
fd.right = new FormAttachment(lblYearChar, 21, SWT.RIGHT);
fd.top = new FormAttachment(btnYearUp, 0, SWT.BOTTOM);
fd.bottom = new FormAttachment(btnYearUp, 10, SWT.BOTTOM);
btnYearDown.setLayoutData(fd);
btnYearDown.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if(year < 9999) {
year++;
lblYear.setText(String.valueOf(year));
if(!chkDisplayAll.getSelection())
refreshRecord(false);
}
}
}
);
// 月标签
lblMonth = new Label(this, SWT.RIGHT);
lblMonth.setText(String.valueOf(month));
fd = new FormData();
fd.left = new FormAttachment(btnYearUp, 5, SWT.RIGHT);
fd.right = new FormAttachment(btnYearUp, 25, SWT.RIGHT);
fd.top = new FormAttachment(0, 0);
lblMonth.setLayoutData(fd);
Label lblMonthChar = new Label(this, SWT.NONE);
lblMonthChar.setText(LumaQQ.getResourceString("record.viewer.label.month"));
fd = new FormData();
fd.left = new FormAttachment(lblMonth, 0, SWT.RIGHT);
fd.top = new FormAttachment(0, 0);
lblMonthChar.setLayoutData(fd);
// 调整月的上按钮
Button btnMonthUp = new Button(this, SWT.ARROW | SWT.UP);
fd = new FormData();
fd.left = new FormAttachment(lblMonthChar, 1, SWT.RIGHT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -