📄 imageselectshell.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.shells;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
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.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import edu.tsinghua.lumaqq.IconHolder;
/**
* 显示一些图像,让用户选择的shell,这些图像必须有相同的长宽
*
* @author 马若劼
*/
public class ImageSelectShell extends ShellAdapter {
private Shell shell;
private Display display;
// 选择的图像代码列表
private List selectedImageCodes;
// IconHolder
private IconHolder icons = IconHolder.getInstance();
// dimension
private Point dimension;
// layout参数
private int horizontalSpacing, verticalSpacing, marginHeight, marginWidth;
// 垂直卷滚条
private ScrollBar vBar;
// 目前共有的image行数
private int lines;
// 容器类,用来实现滚动
private Canvas canvas;
// 是否运行在连续输入模式,连续输入模式是指按住ctrl键不放,可以连续点击输入图像
// 比如在聊天输入框中要输入多个图像时比较有用。缺省为false
private boolean continuous;
// 图像的长宽
private int imageWidth, imageHeight;
// 保存图像和图像码的数组
private List codes, images;
// 当前卷滚条所对应的第一行索引,从0开始
private int row;
// 上一次鼠标在哪个图像上,这是绝对索引,-1表示没有
private int oldIndex;
// 当前鼠标在哪个图像上
private int curIndex;
// 旧图像和新图像的起始坐标
private int oldImageX, oldImageY, curImageX, curImageY;
/**
* 构造函数
* @param parent
*/
public ImageSelectShell(Shell parent) {
display = parent.getDisplay();
shell = new Shell(parent, SWT.NO_TRIM | SWT.V_SCROLL);
shell.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
shell.setLayout(new FormLayout());
shell.addShellListener(this);
// 添加canvas
marginHeight = marginWidth = 0;
verticalSpacing = horizontalSpacing = 5;
canvas = new Canvas(shell, SWT.NONE);
FormData fd = new FormData();
fd.left = fd.top = new FormAttachment(0, marginWidth);
fd.right = fd.bottom = new FormAttachment(100, -marginWidth);
canvas.setLayoutData(fd);
canvas.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
canvas.addPaintListener(
new PaintListener() {
public void paintControl(PaintEvent e) {
// x, y: 绘图起始坐标,image:当前要画的image数组索引
int x = 0, y = 0, image = row * dimension.x;
int size = images.size();
for(int i = 0; i < dimension.y && image < size; i++) {
for(int j = 0; j < dimension.x && image < size; j++) {
e.gc.drawImage((Image)images.get(image), x, y);
image++;
x += imageWidth + horizontalSpacing;
}
y += imageHeight + verticalSpacing;
x = 0;
}
// 在当前图像上画矩形
if(curIndex != -1 && curIndex < images.size())
e.gc.drawRectangle(curImageX, curImageY, imageWidth - 1, imageHeight - 1);
// 重设oldIndex
oldIndex = curIndex;
}
}
);
canvas.addMouseMoveListener(
new MouseMoveListener() {
public void mouseMove(MouseEvent e) {
// 判断现在的鼠标在哪个图像上
int curXIndex = e.x / (imageWidth + horizontalSpacing);
int curYIndex = e.y / (imageHeight + verticalSpacing);
// 得到当前图像的绝对索引
curIndex = dimension.x * (row + curYIndex) + curXIndex;
// 如果旧图像不为-1,则重画
if(oldIndex != -1) {
oldImageX = (oldIndex % dimension.x) * (imageWidth + horizontalSpacing);
oldImageY = (oldIndex / dimension.x - row) * (imageHeight + verticalSpacing);
}
// 如何新旧索引相等,直接返回
if(oldIndex == curIndex) return;
// 重画新图像
curImageX = e.x - e.x % (imageWidth + horizontalSpacing);
curImageY = e.y - e.y % (imageHeight + verticalSpacing);
canvas.redraw();
}
}
);
canvas.addMouseListener(
new MouseAdapter() {
public void mouseUp(MouseEvent e) {
int xIndex = e.x / (imageWidth + horizontalSpacing);
int yIndex = e.y / (imageHeight + verticalSpacing);
// 这下面是判断鼠标是否是在空白地区
if(e.x - xIndex * (imageWidth + horizontalSpacing) > imageWidth ||
e.y - yIndex * (imageHeight + verticalSpacing) > imageHeight)
return;
// 如果不是,那就是在图像之上了,得到图像索引
int image = (row + yIndex) * dimension.x + xIndex;
// 如果图像索引超过了图像总数,也退出
if(image >= images.size()) return;
// 条件都符合,则保存图像代码
selectedImageCodes.add(codes.get(image));
boolean ctrlDown = (e.stateMask & SWT.CTRL) != 0;
if(!(continuous && ctrlDown))
shell.close();
}
}
);
// 初始化变量
selectedImageCodes = new ArrayList();
codes = new ArrayList();
images = new ArrayList();
continuous = false;
oldIndex = curIndex = -1;
dimension = new Point(6, 6);
lines = 0;
vBar = shell.getVerticalBar();
vBar.setMaximum(lines);
vBar.setMinimum(0);
vBar.setIncrement(1);
vBar.addSelectionListener(
new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
row = vBar.getSelection();
curIndex = -1;
canvas.redraw();
}
}
);
setDimension(6, 6);
}
/**
* 设置显示几行几列的图标
* @param x
* @param y
*/
public void setDimension(int x, int y) {
dimension.x = x;
dimension.y = y;
setSize();
}
// 设置shell的size
private void setSize() {
Point barSize = vBar.getSize();
shell.setSize(imageWidth * dimension.x + barSize.x + marginWidth * 2 + horizontalSpacing * (dimension.x - 1), imageHeight * dimension.y + marginHeight * 2 + verticalSpacing * (dimension.y - 1));
}
/**
* 添加一个图像
* @param image
* @param code
*/
public void addImage(Image image, int code) {
codes.add(new Integer(code));
images.add(image);
}
/**
* 刷新当前显示,使添加的图片都显示出来
*/
public void refresh() {
lines = (images.size() + dimension.x - 1) / dimension.x;
setSize();
vBar.setMaximum(lines);
vBar.setThumb(dimension.y);
}
/**
* 添加所有的头像
*/
public void addAllFace() {
for(int i = 0; i < 253; i += 3) {
addImage(icons.getFace(i), i);
}
}
/**
* 添加所有的群头像
*/
public void addAllClusterFace() {
for(int i = 1; i < 7; i++) {
addImage(icons.getClusterFace(i), i);
}
}
/**
* 添加所有的表情
*/
public void addAllSmiley() {
Properties p = new Properties();
try {
p.load(this.getClass().getResourceAsStream("/face_r.properties"));
} catch (IOException e) {
return;
}
for(int i = 0; i <= 95; i++) {
String _code = p.getProperty(String.valueOf(i));
if(_code == null)
continue;
int code = Integer.parseInt(_code);
addImage(icons.getSmiley(code), code);
}
}
// 打开shell
public void open() {
// 打开shell
shell.layout();
shell.open();
}
/**
* 设置窗口位置
* @param x
* @param y
*/
public void setLocation(Point p) {
shell.setLocation(p);
}
/**
* 返回选择的图像代码
* @return 图像代码,这个代码不能改动,由系统处理映射关系
*/
public int getSelectedImageCode() {
if(selectedImageCodes.size() == 0) return -1;
else return ((Integer)selectedImageCodes.get(0)).intValue();
}
/**
* 返回第index个选择的图像代码
* @param index
* @return 图像代码,这个代码不能改动,由系统处理映射关系
*/
public int getSelectedImageCode(int index) {
return ((Integer)selectedImageCodes.get(index)).intValue();
}
/**
* @return 用户点击输入的图像个数
*/
public int getSelectedSize() {
if(continuous)
return selectedImageCodes.size();
else
return 1;
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent e) {
shell.close();
}
/**
* @return true如果窗口已经被disposed
*/
public boolean isDisposed() {
return shell.isDisposed();
}
/**
* 添加shell listener
* @param listener
*/
public void addShellListener(ShellListener listener) {
shell.addShellListener(listener);
}
/**
* @param horizontalSpacing The horizontalSpacing to set.
*/
public void setHorizontalSpacing(int horizontalSpacing) {
this.horizontalSpacing = horizontalSpacing;
}
/**
* @param marginHeight The marginHeight to set.
*/
public void setMarginHeight(int marginHeight) {
this.marginHeight = marginHeight;
}
/**
* @param marginWidth The marginWidth to set.
*/
public void setMarginWidth(int marginWidth) {
this.marginWidth = marginWidth;
FormData fd = (FormData)canvas.getLayoutData();
fd.left.offset = marginWidth;
}
/**
* @param verticalSpacing The verticalSpacing to set.
*/
public void setVerticalSpacing(int verticalSpacing) {
this.verticalSpacing = verticalSpacing;
}
/**
* @return Returns the continuous.
*/
public boolean isContinuous() {
return continuous;
}
/**
* @param continuous The continuous to set.
*/
public void setContinuous(boolean continuous) {
this.continuous = continuous;
}
/**
* @return Returns the imageHeight.
*/
public int getImageHeight() {
return imageHeight;
}
/**
* @param imageHeight The imageHeight to set.
*/
public void setImageHeight(int imageHeight) {
this.imageHeight = imageHeight;
}
/**
* @return Returns the imageWidth.
*/
public int getImageWidth() {
return imageWidth;
}
/**
* @param imageWidth The imageWidth to set.
*/
public void setImageWidth(int imageWidth) {
this.imageWidth = imageWidth;
}
/**
* 设置要显示的图片的统一显示尺寸
* @param x
* @param y
*/
public void setImageSize(int x, int y) {
imageWidth = x;
imageHeight = y;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -