// 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.Dimension;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.infinity.resource.StructEntry;
import org.infinity.util.io.ByteBufferOutputStream;
import org.infinity.util.io.StreamUtils;
public abstract class Datatype implements StructEntry
{
protected static final Dimension DIM_WIDE = new Dimension(800, 100);
protected static final Dimension DIM_BROAD = new Dimension(650, 100);
protected static final Dimension DIM_MEDIUM = new Dimension(450, 100);
private final List<UpdateListener> listeners = new ArrayList<UpdateListener>();
private final int length;
private String name;
private int offset;
private StructEntry parent;
protected Datatype(int offset, int length, String name)
{
this(null, offset, length, name);
}
protected Datatype(StructEntry parent, int offset, int length, String name)
{
this.parent = parent;
this.offset = offset;
this.length = length;
this.name = name;
}
// --------------------- Begin Interface Comparable ---------------------
@Override
public int compareTo(StructEntry o)
{
return offset - o.getOffset();
}
// --------------------- End Interface Comparable ---------------------
// --------------------- Begin Interface StructEntry ---------------------
@Override
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
@Override
public void copyNameAndOffset(StructEntry entry)
{
name = entry.getName();
offset = entry.getOffset();
}
@Override
public StructEntry getParent()
{
return parent;
}
@Override
public String getName()
{
return name;
}
@Override
public int getOffset()
{
return offset;
}
@Override
public int getSize()
{
return length;
}
@Override
public List<StructEntry> getStructChain()
{
List<StructEntry> list = new Vector<StructEntry>();
StructEntry e = this;
while (e != null) {
list.add(0, e);
e = e.getParent();
if (list.contains(e)) {
// avoid infinite loops
break;
}
}
return list;
}
@Override
public void setOffset(int newoffset)
{
offset = newoffset;
}
@Override
public void setParent(StructEntry parent)
{
this.parent = parent;
}
@Override
public ByteBuffer getDataBuffer()
{
ByteBuffer bb = StreamUtils.getByteBuffer(getSize());
try (ByteBufferOutputStream bbos = new ByteBufferOutputStream(bb)) {
write(bbos);
} catch (IOException e) {
e.printStackTrace();
}
bb.position(0);
return bb;
}
// --------------------- End Interface StructEntry ---------------------
/**
* Adds the specified update listener to receive update events from this object.
* If listener l is null, no exception is thrown and no action is performed.
* @param l The update listener
*/
public void addUpdateListener(UpdateListener l)
{
if (l != null) {
listeners.add(l);
}
}
/**
* Returns an array of all update listeners registered on this object.
* @return All of this object's update listener or an empty array if no listener is registered.
*/
public UpdateListener[] getUpdateListeners()
{
UpdateListener[] ar = new UpdateListener[listeners.size()];
for (int i = 0; i < listeners.size(); i++) {
ar[i] = listeners.get(i);
}
return ar;
}
/**
* Removes the specified update listener, so that it no longer receives update events
* from this object.
* @param l The update listener
*/
public void removeUpdateListener(UpdateListener l)
{
if (l != null) {
listeners.remove(l);
}
}
/**
* Notifies all listeners that the value of this Datatype object may have changed.
*/
protected void fireValueUpdated(UpdateEvent event)
{
if (event != null) {
// don't lose current selection
if (event.getStructure().getViewer() != null) {
event.getStructure().getViewer().storeCurrentSelection();
}
boolean retVal = false;
for (final UpdateListener l: listeners) {
retVal |= l.valueUpdated(event);
}
if (retVal) {
event.getStructure().fireTableDataChanged();
}
if (event.getStructure().getViewer() != null) {
event.getStructure().getViewer().restoreCurrentSelection();
}
}
}
void writeInt(OutputStream os, int value) throws IOException
{
if (getSize() == 4) {
StreamUtils.writeInt(os, value);
} else if (getSize() == 3) {
StreamUtils.writeInt24(os, value);
} else if (getSize() == 2) {
StreamUtils.writeShort(os, (short)value);
} else if (getSize() == 1) {
StreamUtils.writeByte(os, (byte)value);
} else {
throw new IllegalArgumentException();
}
}
void writeLong(OutputStream os, long value) throws IOException
{
if (getSize() == 4) {
StreamUtils.writeInt(os, (int)value);
} else if (getSize() == 3) {
StreamUtils.writeInt24(os, (int)value);
} else if (getSize() == 2) {
StreamUtils.writeShort(os, (short)value);
} else if (getSize() == 1) {
StreamUtils.writeByte(os, (byte)value);
} else {
throw new IllegalArgumentException();
}
}
}