// Near Infinity - An Infinity Engine Browser and Editor // Copyright (C) 2001 - 2005 Jon Olav Hauglid // See LICENSE.txt for license information package org.infinity.datatype; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import org.infinity.gui.StructViewer; import org.infinity.gui.TextListPanel; import org.infinity.icon.Icons; import org.infinity.resource.AbstractStruct; import org.infinity.resource.StructEntry; import org.infinity.util.LongIntegerHashMap; import org.infinity.util.ObjectString; public class HashBitmap extends Datatype implements Editable, IsNumeric { private final LongIntegerHashMap<? extends Object> idsmap; private final boolean sortByName; private TextListPanel list; private long value; public HashBitmap(ByteBuffer buffer, int offset, int length, String name, LongIntegerHashMap<? extends Object> idsmap) { this(null, buffer, offset, length, name, idsmap, true); } public HashBitmap(ByteBuffer buffer, int offset, int length, String name, LongIntegerHashMap<? extends Object> idsmap, boolean sortByName) { this(null, buffer, offset, length, name, idsmap, sortByName); } public HashBitmap(StructEntry parent, ByteBuffer buffer, int offset, int length, String name, LongIntegerHashMap<? extends Object> idsmap) { this(parent, buffer, offset, length, name, idsmap, true); } public HashBitmap(StructEntry parent, ByteBuffer buffer, int offset, int length, String name, LongIntegerHashMap<? extends Object> idsmap, boolean sortByName) { super(parent, offset, length, name); this.idsmap = normalizeHashMap(idsmap); this.sortByName = sortByName; read(buffer, offset); } // --------------------- Begin Interface Editable --------------------- @Override public JComponent edit(final ActionListener container) { if (list == null) { long[] keys = idsmap.keys(); List<Object> items = new ArrayList<Object>(keys.length); for (final long id : keys) { if (idsmap.containsKey(id)) { Object o = idsmap.get(id); if (o != null) { items.add(o); } } } list = new TextListPanel(items, sortByName); list.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { if (event.getClickCount() == 2) container.actionPerformed(new ActionEvent(this, 0, StructViewer.UPDATE_VALUE)); } }); } Object selected = idsmap.get(value); if (selected != null) { list.setSelectedValue(selected, true); } JButton bUpdate = new JButton("Update value", Icons.getIcon(Icons.ICON_REFRESH_16)); bUpdate.addActionListener(container); bUpdate.setActionCommand(StructViewer.UPDATE_VALUE); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); JPanel panel = new JPanel(gbl); gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; gbl.setConstraints(list, gbc); panel.add(list); gbc.weightx = 0.0; gbc.fill = GridBagConstraints.NONE; gbc.insets.left = 6; gbl.setConstraints(bUpdate, gbc); panel.add(bUpdate); panel.setMinimumSize(DIM_MEDIUM); panel.setPreferredSize(DIM_MEDIUM); return panel; } @Override public void select() { list.ensureIndexIsVisible(list.getSelectedIndex()); } @Override public boolean updateValue(AbstractStruct struct) { // updating value Object selected = list.getSelectedValue(); if (selected instanceof ObjectString && ((ObjectString)selected).getObject() instanceof Number) { value = ((Number)((ObjectString)selected).getObject()).longValue(); } else { int i = selected.toString().lastIndexOf(" - "); try { value = Long.parseLong(selected.toString().substring(i + 3)); } catch (NumberFormatException e) { return false; } } // notifying listeners fireValueUpdated(new UpdateEvent(this, struct)); return true; } // --------------------- End Interface Editable --------------------- // --------------------- Begin Interface Writeable --------------------- @Override public void write(OutputStream os) throws IOException { writeLong(os, value); } // --------------------- End Interface Writeable --------------------- //--------------------- Begin Interface Readable --------------------- @Override public int read(ByteBuffer buffer, int offset) { buffer.position(offset); switch (getSize()) { case 1: value = buffer.get() & 0xff; break; case 2: value = buffer.getShort() & 0xffff; break; case 4: value = buffer.getInt() & 0xffffffff; break; default: throw new IllegalArgumentException(); } return offset + getSize(); } //--------------------- End Interface Readable --------------------- @Override public String toString() { Object o = idsmap.get(value); if (o == null) { return "Unknown - " + value; } else { return o.toString(); } } //--------------------- Begin Interface IsNumeric --------------------- @Override public long getLongValue() { return value; } @Override public int getValue() { return (int)value; } //--------------------- End Interface IsNumeric --------------------- protected void setValue(long newValue) { this.value = newValue; } public int getListSize() { return idsmap.size(); } public long[] getKeys() { return idsmap.keys(); } public Object getValueOf(long key) { return idsmap.get(Long.valueOf(key)); } public String getSymbol(long index) { Object o = idsmap.get(index); if (o != null) { if (o instanceof ObjectString) { return ((ObjectString)o).getString(); } else { int i = o.toString().lastIndexOf(" - "); if (i >= 0) { return o.toString().substring(0, i); } } } return null; } protected LongIntegerHashMap<? extends Object> getHashBitmap() { return idsmap; } private static LongIntegerHashMap<? extends Object> normalizeHashMap(LongIntegerHashMap<? extends Object> map) { if (map != null && !map.isEmpty() && map.get(map.keys()[0]) instanceof String) { LongIntegerHashMap<ObjectString> retVal = new LongIntegerHashMap<ObjectString>(); long[] keys = map.keys(); for (final long key: keys) { retVal.put(Long.valueOf(key), new ObjectString(map.get(key).toString(), Long.valueOf(key), ObjectString.FMT_OBJECT_HYPHEN)); } return retVal; } else if (map == null) { return new LongIntegerHashMap<ObjectString>(); } else { return map; } } }