/*
* Copyright (c) 2005 (Mike) Maurice Kienenberger (mkienenb@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.gamenet.swing.controls;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.gamenet.application.mm8leveleditor.BinaryFileCompare;
import org.gamenet.application.mm8leveleditor.lod.ProgressDisplayer;
import org.gamenet.util.MonitoredTaskThread;
import org.gamenet.util.SequenceNumberIterator;
import org.gamenet.util.TaskObserver;
public class DataSectionTree extends JTree
{
private boolean multithreaded = true;
private ProgressDisplayer progressDisplayer;
private DataSectionable root;
private String rootName;
private JPopupMenu popup = null;
private JMenuItem compareWithExternalFileMenuItem = null;
private JMenuItem compareWithEachOtherMenuItem = null;
class DataSectionRenderer extends DefaultTreeCellRenderer
{
public DataSectionRenderer()
{
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus)
{
String labelName = ((NamedDataSectionable)value).getLabel();
Component renderer = super.getTreeCellRendererComponent(tree,
value, sel, expanded, leaf, row, hasFocus);
((JLabel) renderer).setText(labelName);
return renderer;
}
}
private static final int INDEX_STEP_COUNT = 10;
interface NamedDataSectionable extends DataSectionable
{
public String getLabel();
}
static class NamedDataSectionableImpl implements NamedDataSectionable
{
private DataSectionable dataSectionable;
private String label;
public boolean equals(Object dataSectionableObject)
{
if (false == dataSectionableObject instanceof NamedDataSectionableImpl) return false;
NamedDataSectionableImpl namedDataSectionableImpl = (NamedDataSectionableImpl)dataSectionableObject;
if (false == namedDataSectionableImpl.getDataSectionable().equals(dataSectionable)) return false;
if (false == namedDataSectionableImpl.getLabel().equals(label)) return false;
return true;
}
public NamedDataSectionableImpl(DataSectionable dataSectionable, String label)
{
this.dataSectionable = dataSectionable;
this.label = label;
}
public String toString()
{
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(hashCode());
stringBuffer.append(":dataSectionable=" + dataSectionable);
stringBuffer.append(",label=" + label);
return stringBuffer.toString();
}
public DataSectionable getDataSectionable()
{
return this.dataSectionable;
}
public String getLabel()
{
return this.label;
}
public DataSection[] getStaticDataSections()
{
return dataSectionable.getStaticDataSections();
}
public Object getData()
{
return dataSectionable.getData();
}
public Object getDataForDataSection(DataSection dataSection)
{
return dataSectionable.getDataForDataSection(dataSection);
}
public Component getComponentForDataSection(TaskObserver taskObserver, String dataSectionName) throws InterruptedException
{
return dataSectionable.getComponentForDataSection(taskObserver, dataSectionName);
}
public Component getListComponentForDataSection(TaskObserver taskObserver, String dataSectionName, List list, Iterator indexIterator) throws InterruptedException
{
return dataSectionable.getListComponentForDataSection(taskObserver, dataSectionName, list, indexIterator);
}
}
static class LeafDataSectionable implements NamedDataSectionable
{
public Object data;
public String label;
public boolean equals(Object dataSectionable)
{
if (false == dataSectionable instanceof LeafDataSectionable) return false;
LeafDataSectionable leafDataSectionable = (LeafDataSectionable)dataSectionable;
if (null == leafDataSectionable.getData())
{
if (null != data) return false;
}
else
{
if (false == leafDataSectionable.getData().equals(data)) return false;
}
if (false == leafDataSectionable.getLabel().equals(label)) return false;
return true;
}
public LeafDataSectionable(Object data, String label)
{
super();
this.data = data;
this.label = label;
}
public String getLabel()
{
return this.label;
}
public DataSection[] getStaticDataSections()
{
return null;
}
public Object getData()
{
return data;
}
public Object getDataForDataSection(DataSection dataSection)
{
return null;
}
public Component getComponentForDataSection(TaskObserver taskObserver, String dataSectionName) throws InterruptedException
{
return null;
}
public Component getListComponentForDataSection(TaskObserver taskObserver, String dataSectionName, List list, Iterator indexIterator) throws InterruptedException
{
return null;
}
}
static class ListItemDataSectionable implements NamedDataSectionable
{
private DataSectionable parentDataSectionable;
private String listID;
private int index;
public boolean equals(Object dataSectionableObject)
{
if (false == dataSectionableObject instanceof ListItemDataSectionable) return false;
ListItemDataSectionable listItemDataSectionable = (ListItemDataSectionable)dataSectionableObject;
if (false == listItemDataSectionable.getParentDataSectionable().equals(parentDataSectionable)) return false;
if (false == listItemDataSectionable.getListID().equals(listID)) return false;
if (listItemDataSectionable.getIndex() != index) return false;
return true;
}
public ListItemDataSectionable(DataSectionable parentDataSectionable, String listID, int index)
{
this.parentDataSectionable = parentDataSectionable;
this.listID = listID;
this.index = index;
}
public String toString()
{
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(hashCode());
stringBuffer.append(":dataSectionable=" + parentDataSectionable);
stringBuffer.append(",listID=" + listID);
stringBuffer.append(",index=" + index);
return stringBuffer.toString();
}
public DataSectionable getParentDataSectionable()
{
return this.parentDataSectionable;
}
public int getIndex()
{
return this.index;
}
public String getLabel()
{
return listID + "[" + String.valueOf(index) + "]";
}
public String getListID()
{
return this.listID;
}
/**
* @return list
*/
public List getList()
{
DataSection childDataSection = getDataSectionForParentAndName(parentDataSectionable, listID);
return (List)parentDataSectionable.getDataForDataSection(childDataSection);
}
public NamedDataSectionable getDataSectionable()
{
return getDataSectionableForParentNameAndIndex(parentDataSectionable, listID, index);
}
public DataSection[] getStaticDataSections()
{
return getDataSectionable().getStaticDataSections();
}
public Object getData()
{
return getDataSectionable().getData();
}
public Object getDataForDataSection(DataSection dataSection)
{
return getDataSectionable().getDataForDataSection(dataSection);
}
public Component getComponentForDataSection(TaskObserver taskObserver, String dataSectionName) throws InterruptedException
{
return getDataSectionable().getComponentForDataSection(taskObserver, dataSectionName);
}
public Component getListComponentForDataSection(TaskObserver taskObserver, String dataSectionName, List list, Iterator indexIterator) throws InterruptedException
{
return getDataSectionable().getListComponentForDataSection(taskObserver, dataSectionName, list, indexIterator);
}
}
static class ListDataSectionable implements NamedDataSectionable
{
private DataSectionable parentDataSectionable;
private String listID;
private int startIndex;
private int endIndex;
private int indexStep;
public boolean equals(Object dataSectionable)
{
if (false == dataSectionable instanceof ListDataSectionable) return false;
ListDataSectionable listDataSectionable = (ListDataSectionable)dataSectionable;
if (false == listDataSectionable.getParentDataSectionable().equals(parentDataSectionable)) return false;
if (listDataSectionable.getStartIndex() != startIndex) return false;
if (listDataSectionable.getEndIndex() != endIndex) return false;
if (listDataSectionable.getIndexStep() != indexStep) return false;
return true;
}
public String getLabel()
{
if (-1 == endIndex)
return listID + "[no elements]";
if (startIndex == endIndex)
return listID + "[" + String.valueOf(endIndex) + "]";
return listID + "[" + String.valueOf(startIndex) + ".." + String.valueOf(endIndex) + "]";
}
private ListDataSectionable(DataSectionable parentDataSectionable, String listID, int startIndex, int endIndex, int indexStep)
{
this.parentDataSectionable = parentDataSectionable;
this.listID = listID;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.indexStep = indexStep;
if (startIndex == endIndex)
{
throw new RuntimeException("Should never reach here: startIndex=" + startIndex + ", endIndex=" + endIndex);
}
}
public int getEndIndex()
{
return this.endIndex;
}
public int getIndexStep()
{
return this.indexStep;
}
public String getListID()
{
return this.listID;
}
public int getStartIndex()
{
return this.startIndex;
}
public int size()
{
return ((endIndex - startIndex) / indexStep) + 1;
}
public NamedDataSectionable getChild(int index) // ind = 2, start=100, end=199, step = 10 => [120..129, 1]
{
if (1 == indexStep)
{
return new ListItemDataSectionable(parentDataSectionable, listID, startIndex + index);
}
else
{
int childStartIndex = (index * indexStep) + startIndex;
int childEndIndex = Math.min(endIndex, childStartIndex + (indexStep - 1));
int childIndexStep = Math.max(1, indexStep / INDEX_STEP_COUNT);
if (childStartIndex == childEndIndex)
{
return new ListItemDataSectionable(parentDataSectionable, listID, childEndIndex);
}
return new ListDataSectionable(parentDataSectionable, listID, childStartIndex, childEndIndex, childIndexStep);
}
}
public String toString()
{
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(hashCode());
stringBuffer.append(":listID=" + listID);
stringBuffer.append(",startIndex=" + String.valueOf(startIndex));
stringBuffer.append(",endIndex=" + String.valueOf(endIndex));
stringBuffer.append(",indexStep=" + String.valueOf(indexStep));
return stringBuffer.toString();
}
public DataSection[] getStaticDataSections()
{
return parentDataSectionable.getStaticDataSections();
}
/**
* @return list
*/
public List getList()
{
DataSection childDataSection = getDataSectionForParentAndName(parentDataSectionable, listID);
return (List)parentDataSectionable.getDataForDataSection(childDataSection);
}
public Object getData()
{
return parentDataSectionable.getData();
}
public Object getDataForDataSection(DataSection dataSection)
{
return parentDataSectionable.getDataForDataSection(dataSection);
}
public Component getComponentForDataSection(TaskObserver taskObserver, String dataSectionName) throws InterruptedException
{
return parentDataSectionable.getComponentForDataSection(taskObserver, dataSectionName);
}
public Component getListComponentForDataSection(TaskObserver taskObserver, String dataSectionName, List list, Iterator indexIterator) throws InterruptedException
{
// IMPLEMENT: probably need own list index iterator
return parentDataSectionable.getListComponentForDataSection(taskObserver, dataSectionName, list, indexIterator);
}
public DataSectionable getParentDataSectionable()
{
return this.parentDataSectionable;
}
public NamedDataSectionable getDataSectionableForIndex(int index)
{
return getDataSectionableForParentNameAndIndex(parentDataSectionable, listID, index);
}
}
public static NamedDataSectionable getDataSectionableForParentNameAndIndex(DataSectionable parentDataSectionable, String childSectionName, int index)
{
DataSection childDataSection = getDataSectionForParentAndName(parentDataSectionable, childSectionName);
Class childDataSectionableClass = childDataSection.getDataSectionableClass();
List childObject = (List)parentDataSectionable.getDataForDataSection(childDataSection);
Object object = childObject.get(index);
String sectionName = childSectionName + "[" + String.valueOf(index) + "]";
if (null == childDataSectionableClass)
return new LeafDataSectionable(object, sectionName);
else return new NamedDataSectionableImpl(constructDataSectionableForNonListObject(childDataSectionableClass, object), sectionName);
}
public static DataSection getDataSectionForParentAndName(DataSectionable parentDataSectionable, String sectionName)
{
DataSection dataSectionArray[] = parentDataSectionable.getStaticDataSections();
for (int index = 0; index < dataSectionArray.length; index++)
{
DataSection section = dataSectionArray[index];
if (section.getDataSectionName() == sectionName) return section;
}
return null;
}
public static DataSectionable constructDataSectionableForNonListObject(Class dataSectionableClass, Object object)
{
if (null == dataSectionableClass) throw new RuntimeException("dataSectionableClass is null.");
if (object instanceof List) throw new RuntimeException("object is List.");
Constructor[] constructorArray = dataSectionableClass.getConstructors();
if (1 != constructorArray.length)
throw new RuntimeException(String.valueOf(constructorArray.length) + " constructors found for class " + dataSectionableClass.getName());
Object[] parameterArray = new Object[] { object };
try
{
return (DataSectionable)constructorArray[0].newInstance(parameterArray);
}
catch (IllegalArgumentException exception)
{
throw new RuntimeException(exception.getMessage(), exception);
}
catch (InstantiationException exception)
{
throw new RuntimeException(exception.getMessage(), exception);
}
catch (IllegalAccessException exception)
{
throw new RuntimeException(exception.getMessage(), exception);
}
catch (InvocationTargetException exception)
{
throw new RuntimeException(exception.getMessage(), exception);
}
}
static class HierarchicalDataSectionableTreeModel implements TreeModel
{
private String rootName;
private DataSectionable rootDataSectionable;
public HierarchicalDataSectionableTreeModel(String rootName, DataSectionable root)
{
super();
this.rootName = rootName;
this.rootDataSectionable = root;
}
public void valueForPathChanged(TreePath path, Object newValue)
{
// TODO Auto-generated method stub
}
public void addTreeModelListener(TreeModelListener l)
{
// TODO Auto-generated method stub
}
public void removeTreeModelListener(TreeModelListener l)
{
// TODO Auto-generated method stub
}
public Object getRoot()
{
return new NamedDataSectionableImpl(rootDataSectionable, rootName);
}
public int getChildCount(Object parentNode)
{
DataSectionable dataSectionable = ((DataSectionable)parentNode);
if (dataSectionable instanceof LeafDataSectionable)
{
return 0;
}
else if (dataSectionable instanceof ListDataSectionable)
{
ListDataSectionable listDataSectionable = (ListDataSectionable)dataSectionable;
return listDataSectionable.size();
}
if (null == dataSectionable.getStaticDataSections()) return 0;
return dataSectionable.getStaticDataSections().length;
}
public boolean isLeaf(Object node)
{
if (null == node) return true;
return (0 == getChildCount(node));
}
private static DataSectionable getDataSectionableForParentAndName(DataSectionable parentDataSectionable, String childSectionName)
{
DataSection childDataSection = getDataSectionForParentAndName(parentDataSectionable, childSectionName);
Object childObject = parentDataSectionable.getDataForDataSection(childDataSection);
if (childObject instanceof List)
{
List list = (List)childObject;
int startIndex = 0;
int endIndex = list.size() - 1;
if (startIndex == endIndex)
return new ListItemDataSectionable(parentDataSectionable, childSectionName, startIndex);
int indexStep = 1;
int displayedSize = list.size();
while (displayedSize > INDEX_STEP_COUNT)
{
displayedSize /= INDEX_STEP_COUNT;
indexStep *= INDEX_STEP_COUNT;
}
return new ListDataSectionable(parentDataSectionable, childSectionName, startIndex, endIndex, indexStep);
}
Class childDataSectionableClass = childDataSection.getDataSectionableClass();
if (null == childDataSectionableClass)
return new LeafDataSectionable(childObject, childSectionName);
else return new NamedDataSectionableImpl(constructDataSectionableForNonListObject(childDataSectionableClass, childObject), childSectionName);
}
public Object getChild(Object parentNode, int index)
{
DataSectionable parentDataSectionable = ((DataSectionable)parentNode);
if (parentDataSectionable instanceof ListDataSectionable)
{
ListDataSectionable listDataSectionable = (ListDataSectionable)parentDataSectionable;
return listDataSectionable.getChild(index);
}
DataSection childDataSection = parentDataSectionable.getStaticDataSections()[index];
return getDataSectionableForParentAndName(parentDataSectionable, childDataSection.getDataSectionName());
}
public int getIndexOfChild(Object parentNode, Object childNode)
{
DataSectionable parentDataSectionable = ((DataSectionable)parentNode);
DataSectionable childDataSectionable = ((DataSectionable)childNode);
DataSection dataSections[] = parentDataSectionable.getStaticDataSections();
for (int index = 0; index < dataSections.length; index++)
{
DataSection childDataSection = parentDataSectionable.getStaticDataSections()[index];
DataSectionable dataSectionable = getDataSectionableForParentAndName(parentDataSectionable, childDataSection.getDataSectionName());
if (childDataSectionable.equals(dataSectionable))
return index;
}
return -1;
}
}
class DataSectionTreeSelectionListener implements TreeSelectionListener
{
public void valueChanged(TreeSelectionEvent e)
{
JTree tree = (JTree) e.getSource();
TreePath treepath = tree.getSelectionPath();
if (null == treepath) return;
NamedDataSectionable parentDataSectionable = null;
if (treepath.getPathCount() > 1)
parentDataSectionable = (NamedDataSectionable)treepath.getPathComponent(treepath.getPathCount() - 2);
NamedDataSectionable namedDataSectionable = (NamedDataSectionable)treepath.getPathComponent(treepath.getPathCount() - 1);
Object object = namedDataSectionable.getData();
if (namedDataSectionable instanceof ListItemDataSectionable)
{
ListItemDataSectionable listItemDataSectionable = (ListItemDataSectionable)namedDataSectionable;
displayList(listItemDataSectionable.getParentDataSectionable(), listItemDataSectionable.getListID(), listItemDataSectionable.getList(), listItemDataSectionable.getIndex(), listItemDataSectionable.getIndex());
return;
}
else if (namedDataSectionable instanceof ListDataSectionable)
{
ListDataSectionable listDataSectionable = (ListDataSectionable)namedDataSectionable;
displayList(listDataSectionable.getParentDataSectionable(), listDataSectionable.getListID(), listDataSectionable.getList(), listDataSectionable.getStartIndex(), listDataSectionable.getEndIndex());
return;
}
else if (null == parentDataSectionable)
{
displayPanel.removeAll();
displayPanel.add(new JLabel("Nothing selected."));
displayPanel.getTopLevelAncestor().validate();
return;
}
else
{
// if (object instanceof byte[])
// {
// ByteDataTableControl bDTC = new ByteDataTableControl((byte[])object, 32, 0);
// displayPanel.removeAll();
// displayPanel.add(bDTC);
// displayPanel.getTopLevelAncestor().validate();
// return;
// }
DataSection dataSection;
if (parentDataSectionable instanceof ListDataSectionable)
{
ListDataSectionable listDataSectionable = (ListDataSectionable)parentDataSectionable;
dataSection = getDataSectionForParentAndName(parentDataSectionable, listDataSectionable.getListID());
}
else
{
dataSection = getDataSectionForParentAndName(parentDataSectionable, namedDataSectionable.getLabel());
}
// IMPLEMENT: probably dump the above
display(parentDataSectionable, dataSection.getDataSectionName());
}
}
private JPanel displayPanel = null;
public DataSectionTreeSelectionListener(JPanel displayPanel)
{
super();
this.displayPanel = displayPanel;
}
private MonitoredTaskThread displayLodEntryThread = null;
public void displayList(final DataSectionable finalizedDataSectionable, final String finalizedDataSectionName, final List list, final int listStartIndex, final int listEndIndex)
{
Runnable displayLodEntryRunnable = new Runnable()
{
public void run()
{
if (multithreaded) displayLodEntryThread.taskProgress(finalizedDataSectionName, 0);
Component displayComponent = null;
try
{
displayComponent = finalizedDataSectionable.getListComponentForDataSection(displayLodEntryThread, finalizedDataSectionName, list, new SequenceNumberIterator(listStartIndex, listEndIndex));
}
catch (InterruptedException exception)
{
displayComponent = new JLabel(
"Error: User cancelled operation.");
}
displayPanel.removeAll();
displayPanel.add(displayComponent);
displayPanel.getTopLevelAncestor().validate();
if (multithreaded) displayLodEntryThread.taskProgress(finalizedDataSectionName, 1);
}
};
if (multithreaded)
{
displayLodEntryThread = new MonitoredTaskThread(
progressDisplayer,
"Please wait.\nRendering data...", "startup",
displayLodEntryRunnable);
displayLodEntryThread.start();
}
else
{
displayLodEntryRunnable.run();
}
}
public void display(final DataSectionable finalizedDataSectionable, final String finalizedDataSectionName)
{
Runnable displayLodEntryRunnable = new Runnable()
{
public void run()
{
if (multithreaded) displayLodEntryThread.taskProgress(finalizedDataSectionName, 0);
Component displayComponent = null;
try
{
displayComponent = finalizedDataSectionable.getComponentForDataSection(displayLodEntryThread, finalizedDataSectionName);
}
catch (InterruptedException exception)
{
displayComponent = new JLabel(
"Error: User cancelled operation.");
}
displayPanel.removeAll();
displayPanel.add(displayComponent);
displayPanel.getTopLevelAncestor().validate();
if (multithreaded) displayLodEntryThread.taskProgress(finalizedDataSectionName, 1);
}
};
if (multithreaded)
{
displayLodEntryThread = new MonitoredTaskThread(
progressDisplayer,
"Please wait.\nRendering data...", "startup",
displayLodEntryRunnable);
displayLodEntryThread.start();
}
else
{
displayLodEntryRunnable.run();
}
}
};
protected DataSectionTree(String rootName, DataSectionable root, JPanel displayPanel, ProgressDisplayer progressDisplayer, boolean multithreaded)
{
this(rootName, root, displayPanel, progressDisplayer);
this.multithreaded = multithreaded;
};
public DataSectionTree(String rootName, DataSectionable root, JPanel displayPanel, ProgressDisplayer progressDisplayer)
{
super(new HierarchicalDataSectionableTreeModel(rootName, root));
this.progressDisplayer = progressDisplayer;
this.rootName = rootName;
this.root = root;
this.setCellRenderer(new DataSectionRenderer());
this.addTreeSelectionListener(new DataSectionTreeSelectionListener(displayPanel));
popup = new JPopupMenu();
compareWithExternalFileMenuItem = new JMenuItem(
"Compare With External Resource");
compareWithExternalFileMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
byte[] oldData = null;
try
{
// File selectedFile =
// this.selectFile(lodFileManager.getExtractionDirectory(),
// this);
File selectedFile = new File("z://file");
FileInputStream fileInputStream = new FileInputStream(
selectedFile);
oldData = new byte[(int) selectedFile.length()];
fileInputStream.read(oldData);
}
catch (FileNotFoundException exception)
{
// TODO Auto-generated catch block
exception.printStackTrace();
}
catch (IOException exception1)
{
// TODO Auto-generated catch block
exception1.printStackTrace();
}
byte newData[] = new byte[0];
BinaryFileCompare.compare(System.err, oldData, newData);
}
});
popup.add(compareWithExternalFileMenuItem);
compareWithEachOtherMenuItem = new JMenuItem("Compare With Each Other");
compareWithEachOtherMenuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JTree tree = (JTree) e.getSource();
TreePath expandedSelectionPaths[] = expandedSelectionPaths(tree.getSelectionPaths());
if (2 == expandedSelectionPaths.length)
{
TreePath treepaths[] = tree.getSelectionPaths();
DataSection firstNode = (DataSection) expandedSelectionPaths[0].getLastPathComponent();
DataSection secondNode = (DataSection) expandedSelectionPaths[1].getLastPathComponent();
if (firstNode.getDataSectionClass() == secondNode.getDataSectionClass())
{
byte firstData[] = new byte[0];
byte secondData[] = new byte[0];
BinaryFileCompare.compare(System.err, firstData, secondData);
}
}
}
});
popup.add(compareWithEachOtherMenuItem);
this.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e)
{
if (false == maybeShowPopup(e))
{
JTree tree = (JTree) e.getSource();
NamedDataSectionable node = (NamedDataSectionable) tree.getLastSelectedPathComponent();
if (null != node)
{
}
else
{
}
}
}
private boolean maybeShowPopup(MouseEvent e)
{
if (e.isPopupTrigger())
{
JTree tree = (JTree) e.getSource();
TreePath expandedSelectionPaths[] = expandedSelectionPaths(tree.getSelectionPaths());
NamedDataSectionable namedDataSectionable = (NamedDataSectionable) tree.getLastSelectedPathComponent();
if (0 == expandedSelectionPaths.length)
{
compareWithExternalFileMenuItem.setEnabled(false);
compareWithEachOtherMenuItem.setEnabled(false);
}
else
{
boolean shouldAllowCompareWithEachOther = false;
if (2 == expandedSelectionPaths.length)
{
NamedDataSectionable firstNode = (NamedDataSectionable)expandedSelectionPaths[0].getLastPathComponent();
NamedDataSectionable secondNode = (NamedDataSectionable)expandedSelectionPaths[1].getLastPathComponent();
if (firstNode.getClass() == secondNode.getClass())
{
shouldAllowCompareWithEachOther = true;
}
}
compareWithEachOtherMenuItem
.setEnabled(shouldAllowCompareWithEachOther);
compareWithExternalFileMenuItem.setEnabled(true);
}
popup.show(e.getComponent(), e.getX(), e.getY());
return true;
}
else
return false;
}
});
}
protected TreePath[] expandedSelectionPaths(TreePath selectedTreePaths[])
{
// Expand all ListDataSectionable paths
List expandedTreePathList = new ArrayList(selectedTreePaths.length);
for (int index = 0; index < selectedTreePaths.length; index++)
{
TreePath path = selectedTreePaths[index];
NamedDataSectionable namedDataSectionable = (NamedDataSectionable) path.getLastPathComponent();
if (namedDataSectionable instanceof ListDataSectionable)
{
ListDataSectionable listDataSectionable = (ListDataSectionable)namedDataSectionable;
for (int listIndex = listDataSectionable.getStartIndex(); listIndex < listDataSectionable.getEndIndex(); listIndex++)
{
expandedTreePathList.add(listDataSectionable.getChild(listIndex - listDataSectionable.getStartIndex()));
}
}
else
{
expandedTreePathList.add(path);
}
}
TreePath expandedSelectionPaths[] = new TreePath[expandedTreePathList.size()];
for (int i = 0; i < expandedTreePathList.size(); i++)
{
expandedSelectionPaths[i] = (TreePath)expandedTreePathList.get(i);
}
return expandedSelectionPaths;
}
}