📄 treemod.java
字号:
/*
* Copyright 2006-2007 Queplix Corp.
*
* Licensed under the Queplix Public License, Version 1.1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.queplix.core.client.common.ui;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.EventPreview;
import java.util.Vector;
/**
* A Tree with different processing of mouse and keyboard-driven events
* All original Tree widget code is licensed by Google Inc.
*
* @see com.google.gwt.user.client.ui.Tree
* @author: Vasily Mikhailitchenko
* @since: 29 Mar 2007
*/
public class TreeMod extends Tree {
private static final String STYLE_NODE_HIGHLIGHTED = "TreeItem-highlighted";
private static final String STYLE_NODE_NORMAL = "gwt-TreeItem";
private static final String TREE_OPEN_IMG = "tree_open.gif";
private static final String TREE_CLOSED_IMG = "tree_closed.gif";
private TreeItem root;
private TreeItem hoverItem;
private TreeItem selectedItem;
private boolean eventPreviewEnabled = false;
/**
* Call this directly after constructor invocation
* @param rootItem - the root Item in the tree
*/
public void setRootItem(TreeItem rootItem) {
this.root = rootItem;
}
private EventPreview ep = new EventPreview(){
public boolean onEventPreview(Event event) {
return processEvent(event);
}
};
public void setEventPreviewEnabled(boolean enabled){
eventPreviewEnabled = enabled;
if(enabled){
DOM.addEventPreview(ep);
} else {
DOM.removeEventPreview(ep);
}
}
public void onBrowserEvent(Event event){
// The TreeMod should respond to clicks before the eventPreview is enabled
if(DOM.eventGetType(event) == Event.ONMOUSEDOWN && !eventPreviewEnabled){
selectElement(root, DOM.eventGetTarget(event));
}
}
public void setFocus(boolean focus){}
private boolean processEvent(Event event) {
int eventType = DOM.eventGetType(event);
switch (eventType) {
case Event.ONMOUSEDOWN: {
// If the user clicks outside of any tree item, pass the event further to browser
return !selectElement(root, DOM.eventGetTarget(event));
}
case Event.ONKEYDOWN: {
if(selectedItem == null){
if(root.getChildCount() > 0){
selectedItem = root.getChild(0);
}
}
char keyCode = (char) DOM.eventGetKeyCode(event);
if (keyCode == KeyboardListener.KEY_UP){
moveHighlightUp(hoverItem);
return false;
} else if (keyCode == KeyboardListener.KEY_DOWN){
moveHighlightDown(hoverItem, true);
return false;
} else if (keyCode == KeyboardListener.KEY_LEFT){
collapseItem(hoverItem);
return false;
} else if (keyCode == KeyboardListener.KEY_RIGHT){
expandItem(hoverItem);
return false;
} else if (keyCode == KeyboardListener.KEY_ENTER){
if(hoverItem != null){
selectItem(hoverItem);
}
return false;
}
break;
}
}
return true;
}
private void collectElementChain(Vector chain, Element hRoot, Element hElem) {
if ((hElem == null) || DOM.compare(hElem, hRoot)) {
return;
}
collectElementChain(chain, hRoot, DOM.getParent(hElem));
chain.add(hElem);
}
private boolean selectElement(TreeItem root, Element hElem) {
Vector chain = new Vector();
collectElementChain(chain, getElement(), hElem);
TreeItem item = findItemByChain(chain, 0, root);
// the state of tree root should be unchangeable, because it is invisible by default
if (item != null && item != this.root) {
String str = hElem.toString();
// TODO: replace with better checking whether the clicked item is a collapse/expand image or the title
if (str.indexOf(TREE_OPEN_IMG) > 0 || str.indexOf(TREE_CLOSED_IMG) > 0) {
item.setState(!item.getState(), true);
return true;
} else if (DOM.isOrHasChild(item.getElement(), hElem)) {
selectItem(item);
return true;
}
}
return false;
}
public void selectItem(TreeItem item) {
selectedItem = item;
if(hoverItem!= null) {
setHighlighted(hoverItem, false);
}
hoverItem = selectedItem;
setSelectedItem(item); // call to underlying item selection method in Tree class
}
private void expandItem(TreeItem item){
if(item.getChildCount() > 0){
item.setState(true, true);
}
}
private void collapseItem(TreeItem item){
if(item.getChildCount() > 0){
item.setState(false, true);
}
}
private TreeItem findItemByChain(Vector chain, int idx, TreeItem root) {
if (idx == chain.size()) {
return root;
}
Element hCurElem = (Element) chain.get(idx);
for (int i = 0, n = root.getChildCount(); i < n; ++i) {
TreeItem child = root.getChild(i);
if (DOM.compare(child.getElement(), hCurElem)) {
TreeItem retItem = findItemByChain(chain, idx + 1, root.getChild(i));
if (retItem == null) {
return child;
}
return retItem;
}
}
return findItemByChain(chain, idx + 1, root);
}
private void moveHighlightDown(TreeItem sel, boolean dig) {
TreeItem parent = sel.getParentItem();
if (parent == null) {
return;
}
int idx = parent.getChildIndex(sel);
if (!dig || !sel.getState()) {
if (idx < parent.getChildCount() - 1) {
onHighlight(parent.getChild(idx + 1));
} else {
moveHighlightDown(parent, false);
}
} else if (sel.getChildCount() > 0) {
onHighlight(sel.getChild(0));
}
}
private void setHighlighted(TreeItem item, boolean highlighted){
item.setStyleName(highlighted ? STYLE_NODE_HIGHLIGHTED : STYLE_NODE_NORMAL);
}
private void onHighlight(TreeItem item) {
setHighlighted(hoverItem, false);
if(item != selectedItem){
setHighlighted(item, true);
}
hoverItem = item;
ensureItemVisible(item);
}
public void ensureItemVisible(TreeItem item){
TreeItem parent = item.getParentItem();
while(parent != null){
parent.setState(true);
parent = parent.getParentItem();
}
DOM.scrollIntoView(item.getElement());
}
private void moveHighlightUp(TreeItem sel) {
if(sel != root.getChild(0)) {
TreeItem parent = sel.getParentItem();
if (parent == null) {
// root is a fake item, it is not displayed by default (see QTree_invisibleRoot CSS class)
// so select its first child
parent = root.getChild(0);
}
int idx = parent.getChildIndex(sel);
if (idx > 0) {
TreeItem sibling = parent.getChild(idx - 1);
onHighlight(findDeepestOpenChild(sibling));
} else {
onHighlight(parent);
}
}
}
private TreeItem findDeepestOpenChild(TreeItem item) {
if (!item.getState()) {
return item;
}
return findDeepestOpenChild(item.getChild(item.getChildCount() - 1));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -