/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.model.tree;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.settings.SettingsListener;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.support.action.swing.ActionList;
import com.eviware.soapui.support.action.swing.ActionListBuilder;
import com.eviware.soapui.support.action.swing.ActionSupport;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
/**
* Abstract base class for SoapUITreeNode implementations
*
* @author Ole.Matzura
*/
public abstract class AbstractModelItemTreeNode<T extends ModelItem> implements SoapUITreeNode, PropertyChangeListener {
private final T modelItem;
private final ModelItem parentItem;
private final SoapUITreeModel treeModel;
private List<? extends SoapUITreeNode> orderItems;
private String orderSetting;
private InternalSettingsListener internalSettingsListener;
protected AbstractModelItemTreeNode(T modelItem, ModelItem parentItem, SoapUITreeModel treeModel) {
this.modelItem = modelItem;
this.parentItem = parentItem;
this.treeModel = treeModel;
modelItem.addPropertyChangeListener(this);
}
public SoapUITreeModel getTreeModel() {
return treeModel;
}
public T getModelItem() {
return modelItem;
}
public boolean valueChanged(Object newValue) {
return false;
}
public boolean isLeaf() {
return getChildCount() == 0;
}
public int getChildCount() {
return orderItems == null ? 0 : orderItems.size();
}
public SoapUITreeNode getChildNode(int index) {
return orderItems == null ? null : orderItems.get(index);
}
public int getIndexOfChild(Object child) {
return orderItems == null ? -1 : orderItems.indexOf(child);
}
public String toString() {
if (modelItem instanceof TestStep) {
return ((TestStep) modelItem).getLabel();
} else if (modelItem instanceof TestCase) {
return ((TestCase) modelItem).getLabel();
}
return modelItem.getName();
}
public JPopupMenu getPopup() {
return ActionSupport.buildPopup(getActions());
}
public ActionList getActions() {
return ActionListBuilder.buildActions(modelItem);
}
public SoapUITreeNode getParentTreeNode() {
return treeModel.getTreeNode(parentItem);
}
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if (propertyName.equals(ModelItem.NAME_PROPERTY) || propertyName.equals(ModelItem.LABEL_PROPERTY)) {
// use this since length has probably changed
getTreeModel().notifyNodeChanged(this);
} else if (propertyName.equals(ModelItem.ICON_PROPERTY)) {
// hack to improve rendering performance
JTree mainTree = SoapUI.getNavigator().getMainTree();
TreePath nodePath = getTreeModel().getPath(this);
Rectangle rowBounds = mainTree.getPathBounds(nodePath);
if (rowBounds != null) {
mainTree.repaint(rowBounds);
}
}
}
public void release() {
modelItem.removePropertyChangeListener(this);
if (internalSettingsListener != null) {
SoapUI.getSettings().removeSettingsListener(internalSettingsListener);
}
getTreeModel().unmapModelItem(modelItem);
}
public <T2 extends SoapUITreeNode> void initOrdering(List<T2> items, String setting) {
this.orderItems = items;
this.orderSetting = setting;
internalSettingsListener = new InternalSettingsListener(this, setting);
SoapUI.getSettings().addSettingsListener(internalSettingsListener);
sortModelItems(items, setting);
}
private final class InternalSettingsListener implements SettingsListener {
private final AbstractModelItemTreeNode<?> node;
private final String setting;
public InternalSettingsListener(AbstractModelItemTreeNode<?> node, String setting) {
this.node = node;
this.setting = setting;
}
public void settingChanged(String name, String newValue, String oldValue) {
if (name.equals(setting)) {
if (oldValue == null) {
oldValue = "false";
}
if (newValue == null) {
newValue = "false";
}
if (!oldValue.equals(newValue)) {
TreePath path = getTreeModel().getPath(AbstractModelItemTreeNode.this);
node.reorder(SoapUI.getNavigator().isVisible(path) && SoapUI.getNavigator().isExpanded(path));
}
}
}
@Override
public void settingsReloaded() {
// TODO Auto-generated method stub
}
}
public void reorder(boolean notify) {
if (orderItems != null) {
sortModelItems(orderItems, orderSetting);
if (notify) {
getTreeModel().notifyStructureChanged(new TreeModelEvent(this, getTreeModel().getPath(this)));
}
}
}
public <T2 extends SoapUITreeNode> void sortModelItems(List<T2> modelItems, final String setting) {
Collections.sort(modelItems, new Comparator<T2>() {
public int compare(T2 o1, T2 o2) {
String name1 = o1.getModelItem().getName();
String name2 = o2.getModelItem().getName();
if (name1 == null && name2 == null) {
return 0;
} else if (name1 == null) {
return -1;
} else if (name2 == null) {
return 1;
} else if (setting != null && SoapUI.getSettings().getBoolean(setting)) {
return name1.compareToIgnoreCase(name2);
} else {
return name1.compareTo(name2);
}
}
});
}
public Enumeration<?> children() {
Vector<TreeNode> children = new Vector<TreeNode>();
for (int c = 0; c < getChildCount(); c++) {
children.add(getChildAt(c));
}
return children.elements();
}
public boolean getAllowsChildren() {
return !isLeaf();
}
public TreeNode getChildAt(int childIndex) {
return getChildNode(childIndex);
}
public int getIndex(TreeNode node) {
return getIndexOfChild(node);
}
public TreeNode getParent() {
return getParentTreeNode();
}
public class ReorderPropertyChangeListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent arg0) {
reorder(true);
SoapUI.getNavigator().selectModelItem((ModelItem) arg0.getSource());
}
}
}