/*
* RapidMiner
*
* Copyright (C) 2001-2008 by Rapid-I and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapid-i.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.operatortree;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTarget;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.ToolTipManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import com.rapidminer.BreakpointListener;
import com.rapidminer.gui.MainFrame;
import com.rapidminer.gui.actions.NewBuildingBlockAction;
import com.rapidminer.gui.actions.NewOperatorAction;
import com.rapidminer.gui.dialog.OperatorInfoScreen;
import com.rapidminer.gui.operatormenu.OperatorMenu;
import com.rapidminer.gui.operatortree.actions.AddAllBreakpointsAction;
import com.rapidminer.gui.operatortree.actions.CollapseAllAction;
import com.rapidminer.gui.operatortree.actions.CopyAction;
import com.rapidminer.gui.operatortree.actions.CutAction;
import com.rapidminer.gui.operatortree.actions.DeleteOperatorAction;
import com.rapidminer.gui.operatortree.actions.ExpandAllAction;
import com.rapidminer.gui.operatortree.actions.InfoOperatorAction;
import com.rapidminer.gui.operatortree.actions.LockTreeStructureAction;
import com.rapidminer.gui.operatortree.actions.PasteAction;
import com.rapidminer.gui.operatortree.actions.RemoveAllBreakpointsAction;
import com.rapidminer.gui.operatortree.actions.RenameOperatorAction;
import com.rapidminer.gui.operatortree.actions.SaveBuildingBlockAction;
import com.rapidminer.gui.operatortree.actions.ToggleActivationItem;
import com.rapidminer.gui.operatortree.actions.ToggleBreakpointItem;
import com.rapidminer.gui.operatortree.actions.ToggleShowDisabledItem;
import com.rapidminer.gui.templates.NewBuildingBlockMenu;
import com.rapidminer.gui.tools.IconSize;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.OperatorChain;
import com.rapidminer.operator.ProcessRootOperator;
/**
* Displays the process definition as a JTree. This is the main process view of the
* RapidMiner GUI and can be used to edit processes. New operators can be added by
* selecting a new operator from the context menu of the currently selected
* operator. This editor also supports cut and paste and drag and drop.
*
* @see com.rapidminer.gui.operatortree.OperatorTreeModel
* @author Ingo Mierswa
* @version $Id: OperatorTree.java,v 1.21 2008/07/13 14:16:10 ingomierswa Exp $
*/
public class OperatorTree extends JTree implements TreeSelectionListener, TreeExpansionListener, MouseListener {
private static final long serialVersionUID = -6934683725946634563L;
// ======================================================================
// Operator Menu Actions and Items
// ======================================================================
public final Action NEW_OPERATOR_ACTION_24 = new NewOperatorAction(this, IconSize.SMALL);
public final Action NEW_OPERATOR_ACTION_32 = new NewOperatorAction(this, IconSize.MIDDLE);
public final Action NEW_BUILDING_BLOCK_ACTION_24 = new NewBuildingBlockAction(this, IconSize.SMALL);
public final Action NEW_BUILDING_BLOCK_ACTION_32 = new NewBuildingBlockAction(this, IconSize.MIDDLE);
public final Action CUT_ACTION_24 = new CutAction(this, IconSize.SMALL);
public final Action CUT_ACTION_32 = new CutAction(this, IconSize.MIDDLE);
public final Action COPY_ACTION_24 = new CopyAction(this, IconSize.SMALL);
public final Action COPY_ACTION_32 = new CopyAction(this, IconSize.MIDDLE);
public final Action PASTE_ACTION_24 = new PasteAction(this, IconSize.SMALL);
public final Action PASTE_ACTION_32 = new PasteAction(this, IconSize.MIDDLE);
public final Action DELETE_OPERATOR_ACTION_24 = new DeleteOperatorAction(this, IconSize.SMALL);
public final Action DELETE_OPERATOR_ACTION_32 = new DeleteOperatorAction(this, IconSize.MIDDLE);
public final Action RENAME_OPERATOR_ACTION_24 = new RenameOperatorAction(this, IconSize.SMALL);
public final Action RENAME_OPERATOR_ACTION_32 = new RenameOperatorAction(this, IconSize.MIDDLE);
public final Action INFO_OPERATOR_ACTION_24 = new InfoOperatorAction(this, IconSize.SMALL);
public final Action INFO_OPERATOR_ACTION_32 = new InfoOperatorAction(this, IconSize.MIDDLE);
public final Action SAVE_BUILDING_BLOCK_ACTION_24 = new SaveBuildingBlockAction(this, IconSize.SMALL);
public final Action SAVE_BUILDING_BLOCK_ACTION_32 = new SaveBuildingBlockAction(this, IconSize.MIDDLE);
public final ToggleBreakpointItem TOGGLE_BREAKPOINT[] = {
new ToggleBreakpointItem(this, BreakpointListener.BREAKPOINT_BEFORE, IconSize.SMALL),
new ToggleBreakpointItem(this, BreakpointListener.BREAKPOINT_WITHIN, IconSize.SMALL),
new ToggleBreakpointItem(this, BreakpointListener.BREAKPOINT_AFTER, IconSize.SMALL)
};
// ======================================================================
// Operator Menu Actions and Items
// ======================================================================
public final ToggleShowDisabledItem TOGGLE_SHOW_DISABLED = new ToggleShowDisabledItem(this, true);
public transient final Action ADD_ALL_BREAKPOINTS_24 = new AddAllBreakpointsAction(this, IconSize.SMALL);
public transient final Action ADD_ALL_BREAKPOINTS_32 = new AddAllBreakpointsAction(this, IconSize.MIDDLE);
public transient final Action REMOVE_ALL_BREAKPOINTS_24 = new RemoveAllBreakpointsAction(this, IconSize.SMALL);
public transient final Action REMOVE_ALL_BREAKPOINTS_32 = new RemoveAllBreakpointsAction(this, IconSize.MIDDLE);
public transient final Action EXPAND_ALL_ACTION_24 = new ExpandAllAction(this, IconSize.SMALL);
public transient final Action EXPAND_ALL_ACTION_32 = new ExpandAllAction(this, IconSize.MIDDLE);
public transient final Action COLLAPSE_ALL_ACTION_24 = new CollapseAllAction(this, IconSize.SMALL);
public transient final Action COLLAPSE_ALL_ACTION_32 = new CollapseAllAction(this, IconSize.MIDDLE);
public transient final LockTreeStructureAction TOGGLE_STRUCTURE_LOCK_ACTION_24 = new LockTreeStructureAction(this, IconSize.SMALL);
public transient final LockTreeStructureAction TOGGLE_STRUCTURE_LOCK_ACTION_32 = new LockTreeStructureAction(this, IconSize.MIDDLE);
/** The main frame. Used for conditional action updates and property table settings. */
private MainFrame mainFrame;
/** The tree model of the operator tree. */
private transient OperatorTreeModel treeModel;
/** The current clip board, i.e. the selected operator before cut or copy was applied. */
private transient Operator clipBoard = null;
/** The drag source of the operator tree */
private DragSource dragSource;
/** The utilities supporting DRAG & DROP operations */
private transient DnDSupport associatedDnDSupport;
/** Indicates if the structure is locked. This means that the structure cannot be
* changed via drag and drop and only parameters can be changed. */
private boolean isStructureLocked = false;
// ======================================================================
/** Creates a new operator tree. */
public OperatorTree(MainFrame mainFrame) {
super();
this.mainFrame = mainFrame;
// the next three lines are necessary to overwrite the default behavior
// for these key strokes
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK), CUT_ACTION_24);
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), COPY_ACTION_24);
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), PASTE_ACTION_24);
// init DnD Support
associatedDnDSupport = new DnDSupport(this);
dragSource = DragSource.getDefaultDragSource();
dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, associatedDnDSupport);
new DropTarget(this, DnDConstants.ACTION_MOVE, associatedDnDSupport, true);
setCellRenderer(new OperatorTreeCellRenderer());
setCellEditor(new OperatorTreeCellEditor(this));
setEditable(true);
setShowsRootHandles(true);
addTreeSelectionListener(this);
addTreeExpansionListener(this);
addMouseListener(this);
ToolTipManager.sharedInstance().registerComponent(this);
setToggleClickCount(5);
// forces the tree to ask the nodes for the correct row heights
// must also be invoked after LaF changes...
setRowHeight(0);
}
protected Object readResolve() {
this.treeModel = new OperatorTreeModel(null, this);
this.clipBoard = null;
this.associatedDnDSupport = new DnDSupport(this);
return this;
}
/** Registers this instance of the operator tree at the drag & drop support */
public DnDSupport getAssociatedDnDSupport() {
return associatedDnDSupport;
}
/** Creates a new operator tree model and restores the expansion state of the complete tree. */
public void setOperator(Operator root) {
// store expansion --> necessary since otherwise the expansion state will be overwritten during model setting
Map<String, Boolean> expansionMap = new HashMap<String, Boolean>();
fillExpansionMap(root, expansionMap);
boolean showDisabled = treeModel != null ? treeModel.showDisabledOperators() : true;
this.treeModel = new OperatorTreeModel(root, this);
this.treeModel.setShowDisabledOperators(showDisabled);
setModel(treeModel);
setRootVisible(true);
// restore expansion
restoreExpansionState(new TreePath(this.treeModel.getRoot()), expansionMap);
expansionMap.clear();
}
private void fillExpansionMap(Operator operator, Map<String, Boolean> expansionMap) {
if (operator instanceof OperatorChain) {
if (operator.isExpanded())
expansionMap.put(operator.getName(), true);
else
expansionMap.put(operator.getName(), false);
}
if (operator instanceof OperatorChain) {
OperatorChain chain = (OperatorChain)operator;
for (Operator child : chain.getAllInnerOperators()) {
fillExpansionMap(child, expansionMap);
}
}
}
private void restoreExpansionState(TreePath path, Map<String, Boolean> expansionMap) {
Operator operator = (Operator)path.getLastPathComponent();
if (operator instanceof OperatorChain) {
OperatorChain chain = (OperatorChain)operator;
for (Operator child : chain.getAllInnerOperators()) {
TreePath childPath = path.pathByAddingChild(child);
restoreExpansionState(childPath, expansionMap);
}
}
if (operator instanceof OperatorChain) {
if (expansionMap.get(operator.getName())) {
expandPath(path);
} else {
collapsePath(path);
}
}
}
/** Returns the currently selected operator, i.e. the last operation in the current selection path. */
public Operator getSelectedOperator() {
TreePath path = getSelectionPath();
if (path == null)
return null;
else
return (Operator) path.getLastPathComponent();
}
/** Returns the current clip board. */
public Operator getClipBoard() {
return clipBoard;
}
/** Returns true if the tree structure is currently locked for drag and drop and
* false otherwise. */
public boolean isStructureLocked() {
return isStructureLocked;
}
/** Sets the current lock status for the drag and drop locking. */
public void setStructureLocked(boolean locked) {
this.isStructureLocked = locked;
TOGGLE_STRUCTURE_LOCK_ACTION_24.updateIcon();
TOGGLE_STRUCTURE_LOCK_ACTION_32.updateIcon();
}
/** Expands the complete tree. */
public void expandAll() {
int row = 0;
while (row < getRowCount()) {
expandRow(row);
row++;
}
}
/** Collapses the complete tree. */
public void collapseAll() {
int row = getRowCount() - 1;
while (row >= 0) {
collapseRow(row);
row--;
}
}
/** This method fires a tree structure changed event for the root operator and causes the complete
* expansion of the tree. Since the complete tree will be restructured after invoking this method this
* method should only be invoked if a complete restructuring of the model occured, e.g. after changing
* view filter setting like filtering disabled operators. Whenever possible
* the method {@link #refresh()} should be used instead which only causes a recursive refresh of the
* already existing operators. */
public void completeRefresh() {
treeModel.fireStructureChanged(this, new TreePath(treeModel.getRoot()));
}
/** This method causes a refresh of the existing operators without restructuring. */
public void refresh() {
refresh(new TreePath(treeModel.getRoot()));
}
/** This method causes a refresh of the given path. */
public void refresh(TreePath path) {
treeModel.fireOperatorChanged(this, path);
Object object = path.getLastPathComponent();
int numberOfChildren = treeModel.getChildCount(object);
for (int i = 0; i < numberOfChildren; i++) {
Object child = treeModel.getChild(object, i);
refresh(path.pathByAddingChild(child));
}
}
/** Cuts the currently selected operator into the clipboard. */
public void cut() {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator != null) {
clipBoard = selectedOperator;
delete();
if (mainFrame != null)
mainFrame.enableActions();
}
}
/** Copies the currently selected operator into the clipboard. */
public void copy() {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator != null) {
clipBoard = selectedOperator.cloneOperator(selectedOperator.getName());
if (mainFrame != null)
mainFrame.enableActions();
}
}
/** Pastes the current clipboard into the tree. */
public void paste() {
if (clipBoard != null) {
insert(clipBoard);
clipBoard = clipBoard.cloneOperator(clipBoard.getName());
}
if (mainFrame != null)
mainFrame.enableActions();
}
/** The currently selected operator will be deleted. */
public void delete() {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator == null)
return;
int index = treeModel.getIndexOfChild(selectedOperator.getParent(), selectedOperator);
selectedOperator.remove();
treeModel.fireOperatorRemoved(this, getSelectionPath().getParentPath(), index, selectedOperator);
if (mainFrame != null) {
mainFrame.processChanged();
mainFrame.enableActions();
}
}
/** The given operator will be inserted at the last position of the currently selected operator chain. */
public void insert(Operator newOperator) {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator == null)
return;
if (selectedOperator instanceof OperatorChain) {
int index = ((OperatorChain) selectedOperator).addOperator(newOperator);
treeModel.fireOperatorInserted(this, getSelectionPath(), index, newOperator);
scrollPathToVisible(getSelectionPath().pathByAddingChild(newOperator));
if (mainFrame != null)
mainFrame.processChanged();
} else {
OperatorChain parentChain = selectedOperator.getParent();
int parentIndex = parentChain.getIndexOfOperator(selectedOperator, true) + 1;
int index = parentChain.addOperator(newOperator, parentIndex);
treeModel.fireOperatorInserted(this, getSelectionPath().getParentPath(), index, newOperator);
scrollPathToVisible(getSelectionPath().getParentPath().pathByAddingChild(newOperator));
if (mainFrame != null)
mainFrame.processChanged();
}
}
/** Renames the currently selected operator. */
public void renameOperator() {
TreePath path = getSelectionPath();
if (path != null) {
// returns immediately... no refresh possible after this method
startEditingAtPath(path);
}
}
/** The currently selected operator will be replaced by the given operator. */
public void replace(Operator operator) {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator == null)
return;
OperatorChain parent = selectedOperator.getParent();
if (parent == null)
return;
int oldPos = treeModel.getIndexOfChild(parent, selectedOperator);
if ((selectedOperator instanceof OperatorChain) && (operator instanceof OperatorChain)) {
OperatorChain chain = (OperatorChain) selectedOperator;
OperatorChain newChain = (OperatorChain) operator;
while (chain.getNumberOfAllOperators() > 0) {
Operator child = chain.getOperatorFromAll(0);
child.remove();
newChain.addOperator(child);
}
}
selectedOperator.remove();
parent.addOperator(operator, oldPos);
TreePath path = getSelectionPath().getParentPath();
treeModel.fireStructureChanged(this, path);
setSelectionPath(path.pathByAddingChild(operator));
if (mainFrame != null)
mainFrame.processChanged();
}
/** Shows the info dialog for the currently selected operator. */
public void showOperatorInfo() {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator != null) {
OperatorInfoScreen infoScreen = new OperatorInfoScreen(mainFrame, selectedOperator);
infoScreen.setVisible(true);
}
}
public void addAllBreakpoints() {
addAllBreakpoints((Operator) treeModel.getRoot());
refresh();
}
private void addAllBreakpoints(Operator operator) {
operator.setBreakpoint(BreakpointListener.BREAKPOINT_BEFORE, false);
operator.setBreakpoint(BreakpointListener.BREAKPOINT_WITHIN, false);
operator.setBreakpoint(BreakpointListener.BREAKPOINT_AFTER, true);
if (operator instanceof OperatorChain) {
OperatorChain chain = (OperatorChain) operator;
for (int i = 0; i < chain.getNumberOfOperators(); i++) {
addAllBreakpoints(chain.getOperator(i));
}
}
}
public void removeAllBreakpoints() {
removeAllBreakpoints((Operator) treeModel.getRoot());
refresh();
}
private void removeAllBreakpoints(Operator operator) {
operator.setBreakpoint(BreakpointListener.BREAKPOINT_BEFORE, false);
operator.setBreakpoint(BreakpointListener.BREAKPOINT_WITHIN, false);
operator.setBreakpoint(BreakpointListener.BREAKPOINT_AFTER, false);
if (operator instanceof OperatorChain) {
OperatorChain chain = (OperatorChain) operator;
for (int i = 0; i < chain.getNumberOfOperators(); i++) {
removeAllBreakpoints(chain.getOperator(i));
}
}
}
/** Toggles if the currently selected operator should be enabled. */
public void toggleOperatorActivation(boolean state) {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator != null) {
selectedOperator.setEnabled(state);
//completeRefresh();
repaint();
if (mainFrame != null)
mainFrame.processChanged();
}
}
/** Toggles if disabled operators should be shown. */
public void toggleShowDisabledOperators() {
treeModel.setShowDisabledOperators(!treeModel.showDisabledOperators());
completeRefresh();
}
/** This method toggles the breakpoint with the given position into the given state. */
public void toggleBreakpoint(int position, boolean state) {
Operator selectedOperator = getSelectedOperator();
if (selectedOperator != null) {
selectedOperator.setBreakpoint(position, state);
TOGGLE_BREAKPOINT[position].setSelected(state);
refresh();
if (mainFrame != null)
mainFrame.processChanged();
}
}
/** This method will be invoked after a user selection of an operator in the tree. Causes
* a property table update and an update of the conditional action container. */
public void valueChanged(TreeSelectionEvent e) {
Operator selectedOperator = getSelectedOperator();
// important in order to save the last editing:
if (mainFrame != null) {
mainFrame.getPropertyTable().editingStopped(new ChangeEvent(this));
mainFrame.getMainProcessEditor().changeFromNewOperator2ParameterEditor();
mainFrame.notifyEditorsOfChange(selectedOperator);
}
if (selectedOperator == null)
return;
if (mainFrame != null)
mainFrame.enableActions();
for (int i = 0; i < TOGGLE_BREAKPOINT.length; i++)
TOGGLE_BREAKPOINT[i].setState(selectedOperator.hasBreakpoint(i));
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
int selRow = getRowForLocation(e.getX(), e.getY());
TreePath selPath = getPathForLocation(e.getX(), e.getY());
if (selRow != -1) {
if (e.getClickCount() == 1) {
evaluateSingleClick(selRow, selPath);
} else if (e.getClickCount() == 2) {
evaluateDoubleClick(selRow, selPath);
}
}
evaluatePopup(e);
}
public void mouseReleased(MouseEvent e) {
evaluatePopup(e);
}
/** Invokes the selection and causes an update of the conditional action list. */
private void evaluateSingleClick(int row, TreePath path) {
setSelectionPath(path);
if (mainFrame != null)
mainFrame.enableActions();
}
/** Removes existing breakpoints or add a new breakpoint after the currently selected operator. */
private void evaluateDoubleClick(int row, TreePath path) {
setSelectionPath(path);
if (getSelectedOperator().hasBreakpoint()) {
toggleBreakpoint(BreakpointListener.BREAKPOINT_BEFORE, false);
toggleBreakpoint(BreakpointListener.BREAKPOINT_WITHIN, false);
toggleBreakpoint(BreakpointListener.BREAKPOINT_AFTER, false);
} else {
toggleBreakpoint(BreakpointListener.BREAKPOINT_AFTER, true);
}
}
/** Checks if the given mouse event is a popup trigger and creates a new popup menu if necessary. */
private void evaluatePopup(MouseEvent e) {
if (e.isPopupTrigger()) {
createOperatorPopupMenu().show(this, e.getX(), e.getY());
}
}
/** Adds the operator tree actions to the given menu. */
public void addOperatorMenuItems(JMenu menu) {
menu.add(RENAME_OPERATOR_ACTION_24);
menu.add(COPY_ACTION_24);
menu.add(CUT_ACTION_24);
menu.add(PASTE_ACTION_24);
menu.add(DELETE_OPERATOR_ACTION_24);
menu.addSeparator();
menu.add(SAVE_BUILDING_BLOCK_ACTION_24);
}
/** Creates a new popup menu for the selected operator. */
private JPopupMenu createOperatorPopupMenu() {
Operator op = getSelectedOperator();
JPopupMenu menu = new JPopupMenu();
if ((op != null) && (op instanceof OperatorChain))
menu.add(OperatorMenu.NEW_OPERATOR_MENU);
if ((op != null) && (!(op instanceof ProcessRootOperator))) {
if ((op instanceof OperatorChain) && (((OperatorChain) op).getNumberOfAllOperators() > 0)) {
menu.add(OperatorMenu.REPLACE_OPERATORCHAIN_MENU);
} else {
menu.add(OperatorMenu.REPLACE_OPERATOR_MENU);
}
}
// add building block menu
if ((op != null) && (op instanceof OperatorChain)) {
final NewBuildingBlockMenu buildingBlockMenu = new NewBuildingBlockMenu();
menu.add(buildingBlockMenu);
buildingBlockMenu.addMenuListener(new MenuListener() {
public void menuCanceled(MenuEvent e) {}
public void menuDeselected(MenuEvent e) {}
public void menuSelected(MenuEvent e) {
buildingBlockMenu.addAllMenuItems();
}
});
}
menu.add(SAVE_BUILDING_BLOCK_ACTION_24);
menu.addSeparator();
menu.add(RENAME_OPERATOR_ACTION_24);
menu.add(DELETE_OPERATOR_ACTION_24);
menu.add(COPY_ACTION_24);
menu.add(CUT_ACTION_24);
menu.add(PASTE_ACTION_24);
menu.addSeparator();
menu.add(INFO_OPERATOR_ACTION_24);
menu.addSeparator();
for (int i = 0; i < TOGGLE_BREAKPOINT.length; i++)
menu.add(TOGGLE_BREAKPOINT[i]);
menu.add(ADD_ALL_BREAKPOINTS_24);
menu.add(REMOVE_ALL_BREAKPOINTS_24);
menu.addSeparator();
menu.add(EXPAND_ALL_ACTION_24);
menu.add(COLLAPSE_ALL_ACTION_24);
menu.add(TOGGLE_STRUCTURE_LOCK_ACTION_24);
menu.addSeparator();
if ((op != null) && (!(op instanceof ProcessRootOperator))) {
ToggleActivationItem activationItem = new ToggleActivationItem(this, op.isEnabled());
if ((op.getParent() != null) && (!op.getParent().isEnabled()))
activationItem.setEnabled(false);
menu.add(activationItem);
}
menu.add(TOGGLE_SHOW_DISABLED);
return menu;
}
public void treeCollapsed(TreeExpansionEvent event) {
Operator operator = (Operator)event.getPath().getLastPathComponent();
operator.setExpanded(false);
if (mainFrame != null)
mainFrame.processChanged();
}
public void treeExpanded(TreeExpansionEvent event) {
Operator operator = (Operator)event.getPath().getLastPathComponent();
operator.setExpanded(true);
if (mainFrame != null)
mainFrame.processChanged();
}
}