📄 qtree.java
字号:
/**
* 得到Item的缩进值
*
* @param level
* 层号
* @return
* 水平缩进象素值
*/
int getItemIndent(int level) {
return level * levelIndent;
}
/**
* 得到item在父item中的y坐标,假设父item是展开的
*
* @param item
* QItem对象
* @return
* y坐标
*/
private int getYInParent(QItem item) {
QItem parentItem = item.getParentItem();
int index = (parentItem == null) ? indexOf(item) : item.getParentItem().indexOf(item);
int y = 0;
int h = getItemHeight(item.getLevel());
for(int i = 0; i < index; i++) {
y += h;
QItem temp = (parentItem == null) ? getItem(i) : parentItem.getItem(i);
if(temp.isExpanded())
y += getItemChildrenHeight(temp);
}
return y;
}
/**
* 得到绝对坐标y下的item对象
*
* @param y
* 绝对坐标y
* @return
* QItem对象,没有返回null
*/
private QItem getItemAtY(int y) {
return getItemAtY(y, null);
}
/**
* 在item的子item中查找y偏移位置的子item
*
* @param y
* y坐标,相对于父item来说
* @param item
* 父item,null表示从根节点开始查找
* @return
* QItem对象,如果没有,返回null
*/
private QItem getItemAtY(int y, QItem item) {
if(y < 0)
return null;
int level = (item == null) ? 0 : (item.getLevel() + 1);
int count = (item == null) ? itemCount : item.getItemCount();
int h = getItemHeight(level);
int i;
for(i = 0; i < count && y >= 0; i++) {
y -= h;
// 如果这个child是展开的,则在其子item中查找
QItem child = (item == null) ? getItem(i) : item.getItem(i);
if(child.isExpanded()) {
QItem ret = getItemAtY(y, child);
if(ret != null)
return ret;
y -= getItemChildrenHeight(child);
}
}
// 如果i还是小于count,则定位到了一个item
if(y < 0)
return (item == null) ? getItem(i - 1) : item.getItem(i - 1);
else
return null;
}
/**
* 得到一个item的所有子item的总高度
*
* @param item
* 父item
* @return
* 子item总高度
*/
private int getItemChildrenHeight(QItem item) {
int count = item.getItemCount();
int ret = 0;
int h = getItemHeight(item.getLevel() + 1);
for(int i = 0; i < count; i++) {
ret += h;
if(item.getItem(i).isExpanded())
ret += getItemChildrenHeight(item.getItem(i));
}
return ret;
}
/**
* 返回某点下的ite对象
*
* @param p
* 相对于客户区的坐标
* @return
* QItem对象,如果坐标下无item,返回null
*/
public QItem getItem(Point p) {
return getItem(p.x, p.y);
}
/**
* 得到第index个子item
*
* @param index
* 子item索引
* @return
* QItem对象
*/
public QItem getItem(int index) {
checkWidget();
checkIndex(index);
return items[index];
}
/**
* 检查index是否符合范围
*
* @param index
* 子item索引
*/
private void checkIndex(int index) {
if(index < 0 || index >= itemCount)
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
/**
* 得到level级的item高度
*
* @param level
* level,从0开始
* @return
* 象素高度
*/
public int getItemHeight(int level) {
checkWidget();
switch(itemLayouts[level]) {
case HORIZONTAL:
return max(fontHeight, itemImageSizes[level]) + ITEM_BOTTOM_MARGIN + ITEM_TOP_MARGIN;
case VERTICAL:
return itemImageSizes[level] + fontHeight + ITEM_BOTTOM_MARGIN + ITEM_TOP_MARGIN + ITEM_IMAGE_TEXT_SPACING;
default:
SWT.error(SWT.ERROR_INVALID_RANGE);
return -1;
}
}
/**
* 得到某层item的宽度
*
* @param level
* 层号
* @return
* item的象素宽度
*/
public int getItemWidth(int level) {
checkWidget();
return clientAreaWidth - getItemIndent(level);
}
/**
* 检查层号参数是否符合要求
*
* @param level
* 层号
*/
private void checkLevel(int level) {
if(level < 0 || level >= MAX_DEEPTH)
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
/**
* 扩展item数组大小
*/
private void expandItemArray() {
QItem[] newItems = new QItem[items.length << 1];
System.arraycopy(items, 0, newItems, 0, itemCount);
items = newItems;
}
/**
* 向item数组中添加一个item到数组中
*
* @param item
* 要添加的QItem对象
*/
private void internalAddItem(QItem item) {
if(itemCount >= items.length)
expandItemArray();
items[itemCount++] = item;
}
/**
* 从item数组中删除一个item,不校验index的合法性
*
* @param index
* item的index
*/
private void internalRemoveItem(int index) {
System.arraycopy(items, index + 1, items, index, itemCount - index - 1);
items[--itemCount] = null;
}
/**
* 计算字体高度
*
* @return
* 字体高度象素
*/
private int calculateFontHeight() {
GC gc = new GC(this);
Font originalFont = gc.getFont();
FontData[] fontDatas = originalFont.getFontData();
FontMetrics metrics = gc.getFontMetrics();
int ascent = metrics.getAscent() + metrics.getLeading();
int descent = metrics.getDescent();
getFontData(fontDatas, SWT.BOLD);
Font boldFont = new Font(getDisplay(), fontDatas);
gc.setFont(boldFont);
metrics = gc.getFontMetrics();
ascent = max(ascent, metrics.getAscent() + metrics.getLeading());
descent = max(descent, metrics.getDescent());
boldFont.dispose();
getFontData(fontDatas, SWT.ITALIC);
Font italicFont = new Font(getDisplay(), fontDatas);
gc.setFont(italicFont);
metrics = gc.getFontMetrics();
ascent = max(ascent, metrics.getAscent() + metrics.getLeading());
descent = max(descent, metrics.getDescent());
italicFont.dispose();
getFontData(fontDatas, SWT.BOLD | SWT.ITALIC);
Font boldItalicFont = new Font(getDisplay(), fontDatas);
gc.setFont(boldItalicFont);
metrics = gc.getFontMetrics();
ascent = max(ascent, metrics.getAscent() + metrics.getLeading());
descent = max(descent, metrics.getDescent());
boldItalicFont.dispose();
gc.setFont(originalFont);
gc.dispose();
return ascent + descent;
}
/**
* 设置font data为某种样式
*
* @param fontDatas
* FontData数组
* @param style
* 样式
*/
private void getFontData(FontData[] fontDatas, int style) {
for(FontData fd : fontDatas)
fd.setStyle(style);
}
/**
* @return Returns the items.
*/
public QItem[] getItems() {
QItem[] ret = new QItem[itemCount];
System.arraycopy(items, 0, ret, 0, itemCount);
return ret;
}
/**
* @return Returns the itemCount.
*/
public int getItemCount() {
return itemCount;
}
/**
* 添加一个item,这个item可能是根节点,也可能是子节点
*
* @param item
* QItem对象
*/
public void addItem(QItem item) {
internalAddItem(item);
}
/**
* 删除一个item
*
* @param index
* item的索引
*/
public void removeItem(int index) {
checkIndex(index);
internalRemoveItem(index);
}
/**
* 删除从index开始的后面所有item
*
* @param index
*/
void removeItemFrom(int index) {
checkIndex(index);
for(int i = index; i < itemCount; i++)
items[index] = null;
itemCount = index;
}
/**
* Item的expanded状态改变之后,重画这个item之下的所有item,并且
* 要更新滚动条
*
* @param item
* 状态发生变化的item
*/
void updateExpanded(QItem item) {
lastChar = 0;
redraw();
setScrollBar();
QTreeEvent e = new QTreeEvent(this, item);
if(item.isExpanded())
sendQTreeExpandedEvent(e);
else
sendQTreeCollapsedEvent(e);
}
/**
* @return
* 所有的item的高度之和,不考虑没有expanded的item
*/
private int getTotalHeight() {
int h = itemCount * getItemHeight(0);
for(int i = 0; i < itemCount; i++) {
if(items[i].isExpanded())
h += getItemChildrenHeight(items[i]);
}
return h;
}
/**
* 调整滚动条参数
*/
private void setScrollBar() {
ScrollBar verticalBar = getVerticalBar();
if (verticalBar != null) {
int totalHeight = getTotalHeight();
verticalBar.setVisible(clientAreaHeight < totalHeight || verticalOffset > 0);
if(verticalBar.getVisible()) {
verticalBar.setValues(verticalOffset,
verticalBar.getMinimum(),
totalHeight + clientAreaHeight - getItemHeight(0),
clientAreaHeight,
10,
clientAreaHeight);
} else {
verticalBar.setMaximum(clientAreaHeight);
verticalBar.setThumb(1);
setVerticalOffset(0, true);
}
}
}
/**
* 重画一个item
*
* @param item
* item对象
*/
void updateItem(QItem item) {
if(!item.isLogicalVisible())
return;
int y = getRelativeYAtItem(item);
int itemHeight = getItemHeight(item.getLevel());
if(y > -itemHeight && y < clientAreaHeight)
redraw(0, y, clientAreaWidth, getItemHeight(item.getLevel()), true);
}
/**
* @return Returns the enableIconHover.
*/
public boolean isEnableIconHover() {
return enableIconHover;
}
/**
* @param enableIconHover The enableIconHover to set.
*/
public void setEnableIconHover(boolean enableIconHover) {
this.enableIconHover = enableIconHover;
}
/**
* 开始一个特效
*
* @param item
* 使用特效的item对象
* @param type
* 特效类型
*/
public void startAnimation(QItem item, Animation type) {
synchronized(animateList) {
if(animateList.contains(item))
return;
animateList.add(item);
item.effect = type.getEffector();
item.animating = true;
}
getDisplay().timerExec(0, animateRunnable);
}
/**
* 停止item的动画
*
* @param item
* 要停止特效的item对象
*/
public void stopAnimation(QItem item) {
synchronized(animateList) {
animateList.remove(item);
item.effect = null;
item.animating = false;
}
updateItem(item);
}
/**
* 停止所有动画
*/
public void stopAllAnimation() {
synchronized(animateList) {
animateList.clear();
}
redraw();
}
/**
* @return Returns the itemUnderMouse.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -