blob: ea0709885f456bfe28d67fb3aea301a7daa56528 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*******************************************************************************/
package org.eclipse.scout.rt.ui.rap.basic.tree;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.scout.commons.CollectionUtility;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.beans.IPropertyObserver;
import org.eclipse.scout.commons.dnd.TransferObject;
import org.eclipse.scout.commons.holders.Holder;
import org.eclipse.scout.commons.job.JobEx;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.rt.client.ui.IDNDSupport;
import org.eclipse.scout.rt.client.ui.IEventHistory;
import org.eclipse.scout.rt.client.ui.action.ActionUtility;
import org.eclipse.scout.rt.client.ui.action.IActionFilter;
import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
import org.eclipse.scout.rt.client.ui.action.menu.TreeMenuType;
import org.eclipse.scout.rt.client.ui.action.menu.root.ITreeContextMenu;
import org.eclipse.scout.rt.client.ui.basic.tree.ITree;
import org.eclipse.scout.rt.client.ui.basic.tree.ITreeNode;
import org.eclipse.scout.rt.client.ui.basic.tree.TreeEvent;
import org.eclipse.scout.rt.client.ui.basic.tree.TreeListener;
import org.eclipse.scout.rt.ui.rap.RwtMenuUtility;
import org.eclipse.scout.rt.ui.rap.basic.RwtScoutComposite;
import org.eclipse.scout.rt.ui.rap.ext.MenuAdapterEx;
import org.eclipse.scout.rt.ui.rap.ext.tree.TreeEx;
import org.eclipse.scout.rt.ui.rap.extension.UiDecorationExtensionPoint;
import org.eclipse.scout.rt.ui.rap.form.fields.AbstractRwtScoutDndSupport;
import org.eclipse.scout.rt.ui.rap.keystroke.IRwtKeyStroke;
import org.eclipse.scout.rt.ui.rap.keystroke.RwtKeyStroke;
import org.eclipse.scout.rt.ui.rap.util.RwtUtility;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.internal.widgets.MarkupValidator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
/**
* @since 3.8.0
*/
@SuppressWarnings("restriction")
public class RwtScoutTree extends RwtScoutComposite<ITree> implements IRwtScoutTree {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(RwtScoutTree.class);
private P_ScoutTreeListener m_scoutTreeListener;
private TreeViewer m_treeViewer;
private boolean m_enabledFromScout = true;
private IRwtKeyStroke[] m_keyStrokes;
private String m_variant = "";
public RwtScoutTree() {
}
public RwtScoutTree(String variant) {
m_variant = variant;
}
@Override
protected void initializeUi(Composite parent) {
TreeViewer viewer = createTreeModel(parent);
setUiTreeViewer(viewer);
setUiField(viewer.getTree());
initNodeHeight();
viewer.getTree().setData(RWT.MARKUP_ENABLED, Boolean.TRUE);
viewer.getTree().setData(MarkupValidator.MARKUP_VALIDATION_DISABLED, Boolean.TRUE);
// listeners
viewer.addSelectionChangedListener(new P_RwtSelectionListener());
viewer.addTreeListener(new P_RwtExpansionListener());
viewer.addDoubleClickListener(new P_RwtDoubleClickListener());
P_RwtTreeListener treeListener = new P_RwtTreeListener();
viewer.getTree().addListener(SWT.Selection, treeListener);
viewer.getTree().addListener(SWT.MouseUp, treeListener);
viewer.getTree().addListener(SWT.MenuDetect, treeListener);
getUiEnvironment().addKeyStroke(viewer.getTree(), new P_RwtToggleKeyStroke(), false);
}
protected TreeViewer createTreeModel(Composite parent) {
int style = isMultiSelect() ? SWT.MULTI : SWT.SINGLE;
style |= SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL;
TreeEx tree = getUiEnvironment().getFormToolkit().createTree(parent, style);
if (StringUtility.hasText(m_variant)) {
tree.setData(RWT.CUSTOM_VARIANT, m_variant);
}
tree.setLayoutDeferred(true);
// Measure item call ends up in a layout error on windows 2000
// tree.addListener(SWT.MeasureItem, new Listener(){
// public void handleEvent(Event event) {
// // event.height = (int)(event.gc.getFontMetrics().getHeight() *1.5);
// }
// });
TreeViewer viewer = new TreeViewer(tree);
viewer.setUseHashlookup(true);
return viewer;
}
@Override
public boolean isUiDisposed() {
return getUiField() == null || getUiField().isDisposed();
}
protected void initializeTreeModel() {
RwtScoutTreeModel model = createTreeModel();
getUiTreeViewer().setContentProvider(model);
getUiTreeViewer().setLabelProvider(model);
getUiTreeViewer().setInput(model);
}
protected RwtScoutTreeModel createTreeModel() {
return new RwtScoutTreeModel(getScoutObject(), this, getUiTreeViewer());
}
protected boolean isMultiSelect() {
if (getScoutObject() != null) {
return getScoutObject().isMultiSelect();
}
else {
return false;
}
}
protected boolean isDragEnabled() {
return getScoutObject().isDragEnabled();
}
protected void setUiTreeViewer(TreeViewer viewer) {
m_treeViewer = viewer;
}
@Override
public TreeViewer getUiTreeViewer() {
return m_treeViewer;
}
protected ITreeContentProvider getContentProvider() {
return (ITreeContentProvider) getUiTreeViewer().getContentProvider();
}
@Override
public TreeEx getUiField() {
return (TreeEx) super.getUiField();
}
protected void initNodeHeight() {
int height = UiDecorationExtensionPoint.getLookAndFeel().getTreeNodeHeight();
if (height >= 0) {
getUiField().setData(RWT.CUSTOM_ITEM_HEIGHT, height);
}
}
@Override
protected void attachScout() {
super.attachScout();
if (getScoutObject() == null) {
return;
}
if (m_scoutTreeListener == null) {
m_scoutTreeListener = new P_ScoutTreeListener();
getScoutObject().addUITreeListener(m_scoutTreeListener);
}
initializeTreeModel();
if (getScoutObject().isRootNodeVisible()) {
setExpansionFromScout(getScoutObject().getRootNode());
}
else {
for (ITreeNode node : getScoutObject().getRootNode().getFilteredChildNodes()) {
setExpansionFromScout(node);
}
}
setSelectionFromScout(CollectionUtility.arrayList(getScoutObject().getSelectedNodes()));
setKeyStrokeFormScout();
setNodeHeightFromScout();
attachDndSupport();
handleEventsFromRecentHistory();
}
protected void attachDndSupport() {
if (UiDecorationExtensionPoint.getLookAndFeel().isDndSupportEnabled()) {
new P_DndSupport(getScoutObject(), getScoutObject(), getUiField());
}
}
private void handleEventsFromRecentHistory() {
//handle events from recent history
final IEventHistory<TreeEvent> h = getScoutObject().getEventHistory();
if (h == null) {
return;
}
getUiEnvironment().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
for (TreeEvent e : h.getRecentEvents()) {
handleScoutTreeEventInUi(e);
}
}
});
}
@Override
protected void detachScout() {
super.detachScout();
if (getScoutObject() == null) {
return;
}
if (m_scoutTreeListener != null) {
getScoutObject().removeTreeListener(m_scoutTreeListener);
m_scoutTreeListener = null;
}
}
@Override
public void setEnabledFromScout(boolean enabled) {
m_enabledFromScout = enabled;
if (getUiField() instanceof TreeEx) {
(getUiField()).setReadOnly(!enabled);
}
else {
getUiField().setEnabled(enabled);
}
}
public boolean isEnabledFromScout() {
return m_enabledFromScout;
}
protected void setExpansionFromScout(ITreeNode scoutNode) {
if (scoutNode != null) {
setExpansionFromScoutRec(scoutNode);
}
}
private void setExpansionFromScoutRec(ITreeNode scoutNode) {
boolean exp;
if (scoutNode.getParentNode() == null) {
exp = true;
}
else {
exp = scoutNode.isExpanded();
}
List<ITreeNode> filteredChildNodes = scoutNode.getFilteredChildNodes();
if (CollectionUtility.hasElements(filteredChildNodes) && exp != getUiTreeViewer().getExpandedState(scoutNode)) {
getUiTreeViewer().setExpandedState(scoutNode, exp);
}
if (exp) {
for (ITreeNode childNode : filteredChildNodes) {
setExpansionFromScoutRec(childNode);
}
}
}
protected void setSelectionFromScout(List<ITreeNode> scoutNodes) {
if (getUiField().isDisposed()) {
return;
}
getUiTreeViewer().setSelection(new StructuredSelection(scoutNodes));
updateScrollToSelectionFromScout();
}
protected void setKeyStrokeFormScout() {
// remove old
if (m_keyStrokes != null) {
for (IRwtKeyStroke keyStroke : m_keyStrokes) {
getUiEnvironment().removeKeyStroke(getUiField(), keyStroke);
}
}
// add new
List<IRwtKeyStroke> newKeyStrokes = new ArrayList<IRwtKeyStroke>();
for (IKeyStroke scoutKeyStroke : getScoutObject().getKeyStrokes()) {
IRwtKeyStroke[] strokes = RwtUtility.getKeyStrokes(scoutKeyStroke, getUiEnvironment());
for (IRwtKeyStroke stroke : strokes) {
getUiEnvironment().addKeyStroke(getUiField(), stroke, false);
newKeyStrokes.add(stroke);
}
}
m_keyStrokes = newKeyStrokes.toArray(new IRwtKeyStroke[newKeyStrokes.size()]);
}
protected void setNodeHeightFromScout() {
int h = getScoutObject().getNodeHeightHint();
if (h >= 0) {
getUiField().setData(RWT.CUSTOM_ITEM_HEIGHT, h);
}
if (isCreated()) {
getUiTreeViewer().refresh();
}
}
/**
* bsi ticket 95090: avoid multiple and excessive tree structure updates
*/
protected void handleScoutTreeEventBatchInUi(List<TreeEvent> eventList) {
//phase 1: collect all parent nodes that need to be refreshed and refresh once per node
HashSet<ITreeNode> processedParentNodes = new HashSet<ITreeNode>();
for (TreeEvent e : eventList) {
ITreeNode parentNode = null;
switch (e.getType()) {
case TreeEvent.TYPE_NODES_INSERTED:
case TreeEvent.TYPE_NODES_UPDATED:
case TreeEvent.TYPE_NODES_DELETED:
case TreeEvent.TYPE_CHILD_NODE_ORDER_CHANGED: {
parentNode = e.getCommonParentNode();
break;
}
case TreeEvent.TYPE_NODE_FILTER_CHANGED: {
parentNode = getScoutObject().getRootNode();
break;
}
}
if (parentNode != null) {
if (!processedParentNodes.contains(parentNode)) {
processedParentNodes.add(parentNode);
updateTreeStructureAndKeepSelection(parentNode);
setExpansionFromScout(parentNode);
}
}
}
//phase 2: apply remaining events
for (TreeEvent e : eventList) {
switch (e.getType()) {
case TreeEvent.TYPE_REQUEST_FOCUS: {
getUiField().setFocus();
break;
}
case TreeEvent.TYPE_NODE_EXPANDED:
case TreeEvent.TYPE_NODE_COLLAPSED: {
setExpansionFromScout(e.getNode());
break;
}
case TreeEvent.TYPE_NODES_SELECTED: {
setSelectionFromScout(CollectionUtility.arrayList(e.getNodes()));
break;
}
case TreeEvent.TYPE_SCROLL_TO_SELECTION: {
scrollToSelection();
break;
}
case TreeEvent.TYPE_NODE_CHANGED: {
updateTreeNode(e.getNode());
break;
}
}
}
}
/**
* Update the given node.
*
* @since 3.10.0-M5
*/
protected void updateTreeNode(ITreeNode node) {
if (getUiTreeViewer() != null) {
getUiTreeViewer().update(node, null);
}
}
private void updateTreeStructureAndKeepSelection(ITreeNode node) {
if (getUiTreeViewer() != null && getUiTreeViewer().getTree() != null && !getUiTreeViewer().getTree().isDisposed()) {
if (node == getScoutObject().getRootNode()) {
getUiTreeViewer().refresh();
}
else {
getUiTreeViewer().refresh(node);
}
}
}
protected void setSelectionFromRwt(final List<ITreeNode> nodes) {
if (getUpdateUiFromScoutLock().isAcquired()) {
return;
}
if (getScoutObject() != null) {
// notify Scout
Runnable t = new Runnable() {
@Override
public void run() {
try {
addIgnoredScoutEvent(TreeEvent.class, "" + TreeEvent.TYPE_NODES_SELECTED);
getScoutObject().getUIFacade().setNodesSelectedFromUI(nodes);
}
finally {
removeIgnoredScoutEvent(TreeEvent.class, "" + TreeEvent.TYPE_NODES_SELECTED);
}
}
};
getUiEnvironment().invokeScoutLater(t, 0);
// end notify
}
}
protected void updateScrollToSelectionFromScout() {
if (getScoutObject().isScrollToSelection()) {
scrollToSelection();
}
}
/**
* @rn imo, 05.03.2009, tickets #73324, #73707, #74018
* @rn imo, 18.11.2009, ticket #83255
*/
protected void scrollToSelection() {
if (getUiField() != null && !getUiField().isDisposed()) {
getUiField().showSelection();
}
}
@Override
protected void handleScoutPropertyChange(String name, Object newValue) {
if (name.equals(ITree.PROP_KEY_STROKES)) {
setKeyStrokeFormScout();
}
else if (name.equals(ITree.PROP_SCROLL_TO_SELECTION)) {
updateScrollToSelectionFromScout();
}
else if (name.equals(ITree.PROP_NODE_HEIGHT_HINT)) {
setNodeHeightFromScout();
}
super.handleScoutPropertyChange(name, newValue);
}
protected void setExpansionFromUi(final ITreeNode node, final boolean expanded) {
if (getUpdateUiFromScoutLock().isAcquired()) {
return;
}
if (getScoutObject() != null) {
// notify Scout
Runnable t = new Runnable() {
@Override
public void run() {
if (node.isExpanded() != expanded) {
getScoutObject().getUIFacade().setNodeExpandedFromUI(node, expanded);
}
}
};
getUiEnvironment().invokeScoutLater(t, 0);
// end notify
}
}
/**
* model thread: scout table observer
*/
protected boolean isHandleScoutTreeEvent(List<? extends TreeEvent> events) {
for (TreeEvent event : events) {
switch (event.getType()) {
case TreeEvent.TYPE_REQUEST_FOCUS:
case TreeEvent.TYPE_NODE_EXPANDED:
case TreeEvent.TYPE_NODE_COLLAPSED:
case TreeEvent.TYPE_NODES_INSERTED:
case TreeEvent.TYPE_NODES_UPDATED:
case TreeEvent.TYPE_NODE_CHANGED:
case TreeEvent.TYPE_NODES_DELETED:
case TreeEvent.TYPE_NODE_FILTER_CHANGED:
case TreeEvent.TYPE_NODES_SELECTED:
case TreeEvent.TYPE_CHILD_NODE_ORDER_CHANGED:
case TreeEvent.TYPE_SCROLL_TO_SELECTION: {
return true;
}
}
}
return false;
}
protected void handleScoutTreeEventInUi(TreeEvent e) {
if (isUiDisposed()) {
return;
}
switch (e.getType()) {
case TreeEvent.TYPE_NODES_INSERTED:
case TreeEvent.TYPE_NODES_DELETED:
case TreeEvent.TYPE_CHILD_NODE_ORDER_CHANGED: {
updateTreeStructureAndKeepSelection(e.getCommonParentNode());
setExpansionFromScout(e.getCommonParentNode());
break;
}
case TreeEvent.TYPE_NODE_CHANGED: {
updateTreeNode(e.getNode());
break;
}
case TreeEvent.TYPE_NODES_UPDATED: {
//in case a virtual node was resolved, check if selection still valid
ISelection oldSelection = getUiTreeViewer().getSelection();
ISelection newSelection = new StructuredSelection(CollectionUtility.arrayList(getScoutObject().getSelectedNodes()));
updateTreeStructureAndKeepSelection(e.getCommonParentNode());
if (!newSelection.equals(oldSelection)) {
getUiTreeViewer().setSelection(newSelection);
}
setExpansionFromScout(e.getCommonParentNode());
break;
}
case TreeEvent.TYPE_NODE_FILTER_CHANGED: {
updateTreeStructureAndKeepSelection(getScoutObject().getRootNode());
setExpansionFromScout(getScoutObject().getRootNode());
break;
}
case TreeEvent.TYPE_REQUEST_FOCUS: {
getUiField().setFocus();
break;
}
case TreeEvent.TYPE_NODE_EXPANDED:
case TreeEvent.TYPE_NODE_COLLAPSED: {
setExpansionFromScout(e.getNode());
break;
}
case TreeEvent.TYPE_NODES_SELECTED: {
setSelectionFromScout(CollectionUtility.arrayList(e.getNodes()));
break;
}
case TreeEvent.TYPE_SCROLL_TO_SELECTION: {
scrollToSelection();
break;
}
}
}
protected void handleUiNodeClick(final ITreeNode node, final int rwtMouseButton) {
if (getScoutObject() != null) {
if (node != null) {
// notify Scout
Runnable t = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireNodeClickFromUI(node, RwtUtility.rwtToScoutMouseButton(rwtMouseButton));
}
};
getUiEnvironment().invokeScoutLater(t, 0);
// end notify
}
}
}
protected void handleUiNodeAction(final ITreeNode node) {
if (getScoutObject() != null) {
// notify Scout
Runnable t = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireNodeActionFromUI(node);
}
};
getUiEnvironment().invokeScoutLater(t, 400);
// end notify
}
}
/**
* TODO not used yet; attach to rwt tree with styled or html cells
*/
protected void handleUiHyperlinkAction(final ITreeNode node, final URL url) {
if (getScoutObject() != null && node != null) {
// notify Scout
Runnable t = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireHyperlinkActionFromUI(node, url);
}
};
getUiEnvironment().invokeScoutLater(t, 0);
// end notify
}
}
// static convenience helpers
public static TreePath scoutNodeToTreePath(ITreeNode scoutNode) {
if (scoutNode == null) {
return null;
}
Object[] path = getPathToRoot(scoutNode, 0);
return new TreePath(path);
}
public static TreePath[] scoutNodesToTreePaths(ITreeNode[] scoutNodes) {
if (scoutNodes == null) {
return new TreePath[0];
}
TreePath[] paths = new TreePath[scoutNodes.length];
for (int i = 0; i < scoutNodes.length; i++) {
paths[i] = scoutNodeToTreePath(scoutNodes[i]);
}
return paths;
}
public static ITreeNode[] getPathToRoot(ITreeNode scoutNode, int depth) {
ITreeNode[] retNodes;
if (scoutNode == null) {
if (depth == 0) {
return null;
}
else {
retNodes = new ITreeNode[depth];
}
}
else {
depth++;
if (scoutNode.getParentNode() == null) {
retNodes = new ITreeNode[depth];
}
else {
retNodes = getPathToRoot(scoutNode.getParentNode(), depth);
}
retNodes[retNodes.length - depth] = scoutNode;
}
return retNodes;
}
/*
* private inner classes
*/
private class P_ScoutTreeListener implements TreeListener {
@Override
public void treeChanged(final TreeEvent e) {
if (isHandleScoutTreeEvent(CollectionUtility.arrayList(e))) {
if (isIgnoredScoutEvent(TreeEvent.class, "" + e.getType())) {
return;
}
Runnable t = new Runnable() {
@Override
public void run() {
try {
getUpdateUiFromScoutLock().acquire();
//
handleScoutTreeEventInUi(e);
}
finally {
getUpdateUiFromScoutLock().release();
}
}
};
getUiEnvironment().invokeUiLater(t);
}
}
@Override
public void treeChangedBatch(final List<? extends TreeEvent> events) {
if (isHandleScoutTreeEvent(events)) {
final List<TreeEvent> filteredList = new ArrayList<TreeEvent>();
for (TreeEvent element : events) {
if (!isIgnoredScoutEvent(TreeEvent.class, "" + element.getType())) {
filteredList.add(element);
}
}
if (CollectionUtility.hasElements(filteredList)) {
Runnable t = new Runnable() {
@Override
public void run() {
try {
getUpdateUiFromScoutLock().acquire();
if (!getUiField().isDisposed()) {
getUiField().setRedraw(false);
}
//
handleScoutTreeEventBatchInUi(filteredList);
}
finally {
getUpdateUiFromScoutLock().release();
if (!getUiField().isDisposed()) {
getUiField().setRedraw(true);
}
}
}
};
getUiEnvironment().invokeUiLater(t);
}
}
}
}// end private class
private class P_RwtSelectionListener implements ISelectionChangedListener {
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (isEnabledFromScout()) {
StructuredSelection sel = (StructuredSelection) event.getSelection();
List<ITreeNode> nodes = new ArrayList<ITreeNode>();
Iterator selectionIt = sel.iterator();
while (selectionIt.hasNext()) {
nodes.add((ITreeNode) selectionIt.next());
}
setSelectionFromRwt(nodes);
}
}
} // end class P_RwtSelectionListener
private Menu createMenu() {
if (getUiField().getMenu() != null) {
getUiField().getMenu().dispose();
getUiField().setMenu(null);
}
Menu contextMenu = new Menu(getUiField().getShell(), SWT.POP_UP);
contextMenu.addMenuListener(new P_ContextMenuListener());
getUiField().setMenu(contextMenu);
return contextMenu;
}
private void createAndShowMenu(Point location) {
Menu menu = createMenu();
showMenu(menu, location);
}
private void showMenu(Menu menu, Point location) {
menu.setLocation(location);
menu.setVisible(true);
}
private void handleUiDoubleClick(StructuredSelection sel) {
@SuppressWarnings("unchecked")
ITreeNode[] nodes = (ITreeNode[]) sel.toList().toArray(new ITreeNode[sel.size()]);
if (nodes != null && nodes.length == 1) {
// if not leaf expand collapse
if (!nodes[0].isLeaf()) {
// invert expansion
setExpansionFromUi(nodes[0], !getUiTreeViewer().getExpandedState(nodes[0]));
}
else {
handleUiNodeAction(nodes[0]);
if (getScoutObject().isCheckable()) {
// on double click it is always the left mouse button
handleUiNodeClick(nodes[0], 1);
}
}
}
}
protected void handleUiToggleAction(Event event) {
if (!event.doit || !getScoutObject().isCheckable()) {
return;
}
if (event.stateMask == 0 && event.keyCode == ' ') {
StructuredSelection sel = (StructuredSelection) getUiTreeViewer().getSelection();
@SuppressWarnings("unchecked")
ITreeNode[] nodes = (ITreeNode[]) sel.toList().toArray(new ITreeNode[sel.size()]);
if (nodes != null && nodes.length > 0) {
handleUiNodeClick(nodes[0], event.button);
}
event.doit = false;
}
}
private class P_RwtTreeListener implements Listener {
private static final long serialVersionUID = 1L;
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Selection: {
ViewerCell cell = getUiTreeViewer().getCell(new Point(event.x, event.y));
if (cell != null && cell.getBounds().contains(event.x, event.y) && cell.getElement() instanceof ITreeNode) {
ITreeNode nodeToClick = (ITreeNode) cell.getElement();
handleUiNodeClick(nodeToClick, event.button);
}
break;
}
case SWT.Resize: {
updateScrollToSelectionFromScout();
break;
}
case SWT.MenuDetect: {
Point eventPosition = new Point(event.x, event.y);
createAndShowMenu(eventPosition);
break;
}
}
}
}
private class P_RwtExpansionListener implements ITreeViewerListener {
@Override
public void treeCollapsed(TreeExpansionEvent event) {
setExpansionFromUi((ITreeNode) event.getElement(), false);
}
@Override
public void treeExpanded(TreeExpansionEvent event) {
setExpansionFromUi((ITreeNode) event.getElement(), true);
}
} // end class P_RwtExpansionListener
private class P_RwtToggleKeyStroke extends RwtKeyStroke {
private static final long serialVersionUID = 1L;
public P_RwtToggleKeyStroke() {
super(' ');
}
@Override
public void handleUiAction(Event e) {
handleUiToggleAction(e);
}
} // end class P_RwtKeyReturnAvoidDoubleClickListener
private class P_RwtDoubleClickListener implements IDoubleClickListener {
@Override
public void doubleClick(DoubleClickEvent event) {
if (event.getSelection() instanceof StructuredSelection) {
StructuredSelection sel = (StructuredSelection) event.getSelection();
handleUiDoubleClick(sel);
}
}
}
private class P_ContextMenuListener extends MenuAdapterEx {
private static final long serialVersionUID = 1L;
public P_ContextMenuListener() {
super(RwtScoutTree.this.getUiTreeViewer().getTree(), RwtScoutTree.this.getUiTreeViewer().getTree().getParent());
}
@Override
public void menuShown(MenuEvent e) {
super.menuShown(e);
if (getScoutObject() == null || !isEnabledFromScout()) {
return;
}
ITreeContextMenu contextMenu = getScoutObject().getContextMenu();
final IActionFilter aboutToShowFilter;
if ((getUiField().getContextItem() == null)) {
aboutToShowFilter = ActionUtility.createMenuFilterMenuTypes(CollectionUtility.hashSet(TreeMenuType.EmptySpace), false);
}
else {
aboutToShowFilter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), false);
}
Runnable t = new Runnable() {
@Override
public void run() {
getScoutObject().getContextMenu().callAboutToShow(aboutToShowFilter);
}
};
JobEx job = getUiEnvironment().invokeScoutLater(t, 1200);
try {
job.join(1200);
}
catch (InterruptedException ex) {
//nop
}
final IActionFilter displayFilter;
if ((getUiField().getContextItem() == null)) {
displayFilter = ActionUtility.createMenuFilterMenuTypes(CollectionUtility.hashSet(TreeMenuType.EmptySpace), true);
}
else {
displayFilter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), true);
}
RwtMenuUtility.fillMenu(((Menu) e.getSource()), contextMenu.getChildActions(), displayFilter, getUiEnvironment());
}
} // end class P_ContextMenuListener
private class P_DndSupport extends AbstractRwtScoutDndSupport {
public P_DndSupport(IPropertyObserver scoutObject, IDNDSupport scoutDndSupportable, Control control) {
super(scoutObject, scoutDndSupportable, control, RwtScoutTree.this.getUiEnvironment());
}
@Override
protected DragSource createDragSource(Control control) {
if (isDragEnabled()) {
return new DragSource(control, DND.DROP_COPY | DND.DROP_MOVE);
}
return null;
}
@Override
protected TransferObject handleUiDragRequest() {
final Holder<TransferObject> result = new Holder<TransferObject>(TransferObject.class, null);
Runnable t = new Runnable() {
@Override
public void run() {
TransferObject scoutTransferable = getScoutObject().getUIFacade().fireNodesDragRequestFromUI();
result.setValue(scoutTransferable);
}
};
try {
getUiEnvironment().invokeScoutLater(t, 20000).join(20000);
}
catch (InterruptedException e) {
//nop
}
return result.getValue();
}
@Override
protected void handleUiDragFinished() {
Runnable t = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireDragFinishedFromUI();
}
};
try {
getUiEnvironment().invokeScoutLater(t, 20000).join(20000);
}
catch (InterruptedException e) {
//nop
}
}
@Override
protected void handleUiDropAction(DropTargetEvent event, final TransferObject scoutTransferObject) {
Object dropTarget = event.item != null ? event.item.getData() : null;
final ITreeNode node = dropTarget instanceof ITreeNode ? (ITreeNode) dropTarget : null;
Runnable job = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireNodeDropActionFromUI(node, scoutTransferObject);
}
};
getUiEnvironment().invokeScoutLater(job, 200);
}
@Override
protected void handleUiDropTargetChanged(DropTargetEvent event) {
Object dropTarget = event.item != null ? event.item.getData() : null;
final ITreeNode node = dropTarget instanceof ITreeNode ? (ITreeNode) dropTarget : null;
Runnable job = new Runnable() {
@Override
public void run() {
getScoutObject().getUIFacade().fireNodeDropTargetChangedFromUI(node);
}
};
getUiEnvironment().invokeScoutLater(job, 200);
}
}// end class P_DndSupport
}