// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.gui.hexview;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.infinity.gui.DataMenuItem;
import org.infinity.gui.StructViewer;
import org.infinity.gui.ViewFrame;
import org.infinity.resource.AbstractStruct;
import org.infinity.resource.StructEntry;
import tv.porst.jhexview.IMenuCreator;
import tv.porst.jhexview.JHexView;
/**
* Provides a dynamic popupmenu for the StructHexViewer component.
*/
public class ResourceMenuCreator extends MenuCreator implements IMenuCreator, ActionListener
{
private final AbstractStruct struct;
public ResourceMenuCreator(JHexView hexView, AbstractStruct struct)
{
super(hexView);
if (struct == null) {
throw new NullPointerException("struct is null");
}
this.struct = struct;
}
//--------------------- Begin Interface IMenuCreator ---------------------
@Override
public JPopupMenu createMenu(long offset)
{
// generating popup menu
JPopupMenu popup = super.createMenu(offset);
// adding dynamic entries on top of popup menu
List<JMenuItem> list = createStructEntries((int)offset);
if (!list.isEmpty()) {
popup.add(new JPopupMenu.Separator(), 0);
popup.addSeparator();
}
for (int i = list.size() - 1; i >= 0; i--) {
final JMenuItem mi = list.get(i);
mi.addActionListener(this);
popup.add(mi, 0);
}
return popup;
}
//--------------------- End Interface IMenuCreator ---------------------
//--------------------- Begin Interface ActionListener ---------------------
@Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() instanceof DataMenuItem) {
DataMenuItem mi = (DataMenuItem)e.getSource();
StructEntry entry = (StructEntry)mi.getData();
if (entry != null) {
List<StructEntry> listEntries = entry.getStructChain();
StructViewer curViewer = null;
for (int i = 0; i < listEntries.size(); i++) {
entry = listEntries.get(i);
if (entry instanceof AbstractStruct) {
if (entry == getStruct()) {
curViewer = ((AbstractStruct)entry).getViewer();
if (curViewer != null) {
curViewer.selectEditTab();
curViewer.selectEntry(entry.getOffset(), false);
}
} else {
if (curViewer != null) {
curViewer.selectEntry(entry.getOffset(), false);
}
ViewFrame curFrame = curViewer.getViewFrame((AbstractStruct)entry);
if (curFrame.getViewable() instanceof AbstractStruct) {
curViewer = ((AbstractStruct)curFrame.getViewable()).getViewer();
} else {
curViewer = null;
}
}
} else if (curViewer != null) {
curViewer.selectEntry(entry.getOffset(), false);
curViewer = null;
}
}
}
} else {
super.actionPerformed(e);
}
}
//--------------------- End Interface ActionListener ---------------------
/** Returns the associated resource structure instance. */
public AbstractStruct getStruct()
{
return struct;
}
// Creates a list of all structures containing the specified offset, starting from topmost level.
private List<JMenuItem> createStructEntries(int offset)
{
List<JMenuItem> list = new ArrayList<JMenuItem>();
if (getHexView().getData() instanceof StructuredDataProvider) {
StructEntry curEntry = ((StructuredDataProvider)getHexView().getData()).getFieldAt(offset);
if (curEntry != null) {
List<StructEntry> listEntries = curEntry.getStructChain();
// we don't need actual resource structure
if (!listEntries.isEmpty() && listEntries.get(0) == getStruct()) {
listEntries.remove(0);
}
for (int i = 0; i < listEntries.size(); i++) {
StructEntry e = listEntries.get(i);
JMenuItem mi = new DataMenuItem(String.format("Go to \"%1$s\"", e.getName()), null, e);
list.add(mi);
}
}
}
return list;
}
}