// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.resource.chu;
import java.awt.Dimension;
import java.awt.Point;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import org.infinity.datatype.Bitmap;
import org.infinity.datatype.ColorPicker;
import org.infinity.datatype.DecNumber;
import org.infinity.datatype.Flag;
import org.infinity.datatype.HexNumber;
import org.infinity.datatype.ResourceRef;
import org.infinity.datatype.StringRef;
import org.infinity.datatype.TextString;
import org.infinity.datatype.Unknown;
import org.infinity.resource.AbstractStruct;
import org.infinity.resource.Profile;
final class Control extends AbstractStruct // implements AddRemovable
{
// CHU/Control-specific field labels
public static final String CHU_CONTROL = "Control";
public static final String CHU_CONTROL_OFFSET = "Offset";
public static final String CHU_CONTROL_LENGTH = "Length";
public static final String CHU_CONTROL_ID = "Control ID";
public static final String CHU_CONTROL_BUFFER_LENGTH = "Buffer length";
public static final String CHU_CONTROL_POSITION_X = "Position: X";
public static final String CHU_CONTROL_POSITION_Y = "Position: Y";
public static final String CHU_CONTROL_WIDTH = "Width";
public static final String CHU_CONTROL_HEIGHT = "Height";
public static final String CHU_CONTROL_TYPE = "Type";
public static final String CHU_CONTROL_BTN_RESREF = "Button";
public static final String CHU_CONTROL_BTN_ANIMATION_INDEX = "Animation number";
public static final String CHU_CONTROL_BTN_FLAGS = "Text flags";
public static final String CHU_CONTROL_BTN_FRAME_INDEX_UNPRESSED = "Frame number: Unpressed";
public static final String CHU_CONTROL_BTN_FRAME_INDEX_PRESSED = "Frame number: Pressed";
public static final String CHU_CONTROL_BTN_FRAME_INDEX_SELECTED = "Frame number: Selected";
public static final String CHU_CONTROL_BTN_FRAME_INDEX_DISABLED = "Frame number: Disabled";
public static final String CHU_CONTROL_BTN_TEXT_ANCHOR_LEFT = "Text anchor: Left";
public static final String CHU_CONTROL_BTN_TEXT_ANCHOR_RIGHT = "Text anchor: Right";
public static final String CHU_CONTROL_BTN_TEXT_ANCHOR_TOP = "Text anchor: Top";
public static final String CHU_CONTROL_BTN_TEXT_ANCHOR_BOTTOM = "Text anchor: Bottom";
public static final String CHU_CONTROL_SLD_BACKGROUND = "Background image";
public static final String CHU_CONTROL_SLD_KNOB = "Slider knob";
public static final String CHU_CONTROL_SLD_ANIMATION_INDEX = "Animation number";
public static final String CHU_CONTROL_SLD_FRAME_INDEX_UNGRABBED = "Frame number: Ungrabbed";
public static final String CHU_CONTROL_SLD_FRAME_INDEX_GRABBED = "Frame number: Grabbed";
public static final String CHU_CONTROL_SLD_KNOB_POSITION_X = "Knob position: X";
public static final String CHU_CONTROL_SLD_KNOB_POSITION_Y = "Knob position: Y";
public static final String CHU_CONTROL_SLD_STEP_WIDTH = "Step width";
public static final String CHU_CONTROL_SLD_STEP_COUNT = "Step count";
public static final String CHU_CONTROL_SLD_REGION_TOP = "Slider region: Top";
public static final String CHU_CONTROL_SLD_REGION_BOTTOM = "Slider region: Bottom";
public static final String CHU_CONTROL_SLD_REGION_LEFT = "Slider region: Left";
public static final String CHU_CONTROL_SLD_REGION_RIGHT = "Slider region: Right";
public static final String CHU_CONTROL_TF_BACKGROUND_1 = "Background 1";
public static final String CHU_CONTROL_TF_BACKGROUND_2 = "Background 2";
public static final String CHU_CONTROL_TF_BACKGROUND_3 = "Background 3";
public static final String CHU_CONTROL_TF_CARET = "Caret";
public static final String CHU_CONTROL_TF_ANIMATION_INDEX = "Animation number";
public static final String CHU_CONTROL_TF_FRAME_INDEX = "Frame number";
public static final String CHU_CONTROL_TF_CARET_POSITION_X = "Caret position: X";
public static final String CHU_CONTROL_TF_CARET_POSITION_Y = "Caret position: Y";
public static final String CHU_CONTROL_TF_ID = "Text field ID";
public static final String CHU_CONTROL_TF_FONT = "Font";
public static final String CHU_CONTROL_TF_TEXT = "Initial text";
public static final String CHU_CONTROL_TF_FIELD_LENGTH = "Field length";
public static final String CHU_CONTROL_TF_ALLOWED_CSE = "Allowed case";
public static final String CHU_CONTROL_TA_FONT_MAIN = "Font (main text)";
public static final String CHU_CONTROL_TA_FONT_INITIALS = "Font (initials)";
public static final String CHU_CONTROL_TA_COLOR_1 = "Color 1";
public static final String CHU_CONTROL_TA_COLOR_2 = "Color 2";
public static final String CHU_CONTROL_TA_COLOR_3 = "Color 3";
public static final String CHU_CONTROL_TA_SCROLLBAR_ID = "Scroll bar ID";
public static final String CHU_CONTROL_LBL_TEXT = "Initial text";
public static final String CHU_CONTROL_LBL_FONT = "Font";
public static final String CHU_CONTROL_LBL_COLOR_1 = "Color 1";
public static final String CHU_CONTROL_LBL_COLOR_2 = "Color 2";
public static final String CHU_CONTROL_LBL_FLAGS = "Text flags";
public static final String CHU_CONTROL_SB_GRAPHICS = "Graphics";
public static final String CHU_CONTROL_SB_ANIMATION_INDEX = "Animation number";
public static final String CHU_CONTROL_SB_FRAME_INDEX_UP_UNPRESSED = "Frame number: Up-arrow, unpressed";
public static final String CHU_CONTROL_SB_FRAME_INDEX_UP_PRESSED = "Frame number: Up-arrow, pressed";
public static final String CHU_CONTROL_SB_FRAME_INDEX_DOWN_UNPRESSED = "Frame number: Down-arrow, unpressed";
public static final String CHU_CONTROL_SB_FRAME_INDEX_DOWN_PRESSED = "Frame number: Down-arrow, pressed";
public static final String CHU_CONTROL_SB_FRAME_INDEX_TROUGH = "Frame number: Trough";
public static final String CHU_CONTROL_SB_FRAME_INDEX_SLIDER = "Frame number: Slider";
public static final String CHU_CONTROL_SB_TEXT_ID = "Text area ID";
private static final String[] s_type = {"Button", "", "Slider", "Text field", "",
"Text area", "Label", "Scroll bar"};
private static final String[] s_button = {"Center", "Left justify", "Right justify",
"Top justify", "Bottom justify", "Anchor",
"Reduce size", "Don't wrap"};
private static final String[] s_label = {"Center", "Use color", "Truecolor", "Center justify",
"Left justify", "Right justify", "Top justify",
"Middle justify", "Bottom justify", "Word wrap"};
private static final String[] s_case = {"Normal case", "Upper case only", "Lower case only"};
private final int size;
Control(AbstractStruct superStruct, ByteBuffer buffer, int offset, int number, int size) throws Exception
{
super(superStruct, CHU_CONTROL + " " + number, buffer, offset);
this.size = size;
}
// --------------------- Begin Interface Writeable ---------------------
@Override
public void write(OutputStream os) throws IOException
{
getField(0).write(os);
getField(1).write(os);
}
// --------------------- End Interface Writeable ---------------------
@Override
public int read(ByteBuffer buffer, int offset)
{
addField(new HexNumber(buffer, offset, 4, CHU_CONTROL_OFFSET));
addField(new HexNumber(buffer, offset + 4, 4, CHU_CONTROL_LENGTH));
return offset + 8;
}
public int getControlSize()
{
return size;
}
/** Returns the control id. */
public int getControlId()
{
return ((DecNumber)getAttribute(CHU_CONTROL_ID)).getValue();
}
/** Returns the x and y position of the control. */
public Point getControlPosition()
{
return new Point(((DecNumber)getAttribute(CHU_CONTROL_POSITION_X)).getValue(),
((DecNumber)getAttribute(CHU_CONTROL_POSITION_Y)).getValue());
}
/** Returns the width and height of the control. */
public Dimension getControlDimensions()
{
return new Dimension(((DecNumber)getAttribute(CHU_CONTROL_WIDTH)).getValue(),
((DecNumber)getAttribute(CHU_CONTROL_HEIGHT)).getValue());
}
/** Returns the control type. */
public int getControlType()
{
return ((Bitmap)getAttribute(CHU_CONTROL_TYPE)).getValue();
}
public int readControl(ByteBuffer buffer)
{
int offset = ((HexNumber)getAttribute(CHU_CONTROL_OFFSET)).getValue();
int endOffset = offset + getControlSize();
addField(new DecNumber(buffer, offset, 2, CHU_CONTROL_ID));
addField(new DecNumber(buffer, offset + 2, 2, CHU_CONTROL_BUFFER_LENGTH));
addField(new DecNumber(buffer, offset + 4, 2, CHU_CONTROL_POSITION_X));
addField(new DecNumber(buffer, offset + 6, 2, CHU_CONTROL_POSITION_Y));
addField(new DecNumber(buffer, offset + 8, 2, CHU_CONTROL_WIDTH));
addField(new DecNumber(buffer, offset + 10, 2, CHU_CONTROL_HEIGHT));
Bitmap type = new Bitmap(buffer, offset + 12, 1, CHU_CONTROL_TYPE, s_type);
addField(type);
addField(new Unknown(buffer, offset + 13, 1));
switch (type.getValue()) {
case 0: // Button
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_BTN_RESREF, "BAM"));
addField(new DecNumber(buffer, offset + 22, 1, CHU_CONTROL_BTN_ANIMATION_INDEX));
addField(new Flag(buffer, offset + 23, 1, CHU_CONTROL_BTN_FLAGS, s_button));
addField(new DecNumber(buffer, offset + 24, 1, CHU_CONTROL_BTN_FRAME_INDEX_UNPRESSED));
addField(new DecNumber(buffer, offset + 25, 1, CHU_CONTROL_BTN_TEXT_ANCHOR_LEFT));
addField(new DecNumber(buffer, offset + 26, 1, CHU_CONTROL_BTN_FRAME_INDEX_PRESSED));
addField(new DecNumber(buffer, offset + 27, 1, CHU_CONTROL_BTN_TEXT_ANCHOR_RIGHT));
addField(new DecNumber(buffer, offset + 28, 1, CHU_CONTROL_BTN_FRAME_INDEX_SELECTED));
addField(new DecNumber(buffer, offset + 29, 1, CHU_CONTROL_BTN_TEXT_ANCHOR_TOP));
addField(new DecNumber(buffer, offset + 30, 1, CHU_CONTROL_BTN_FRAME_INDEX_DISABLED));
addField(new DecNumber(buffer, offset + 31, 1, CHU_CONTROL_BTN_TEXT_ANCHOR_BOTTOM));
offset += 32;
break;
case 2: // Slider
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_SLD_BACKGROUND, "MOS"));
addField(new ResourceRef(buffer, offset + 22, CHU_CONTROL_SLD_KNOB, "BAM"));
addField(new DecNumber(buffer, offset + 30, 2, CHU_CONTROL_SLD_ANIMATION_INDEX));
addField(new DecNumber(buffer, offset + 32, 2, CHU_CONTROL_SLD_FRAME_INDEX_UNGRABBED));
addField(new DecNumber(buffer, offset + 34, 2, CHU_CONTROL_SLD_FRAME_INDEX_GRABBED));
addField(new DecNumber(buffer, offset + 36, 2, CHU_CONTROL_SLD_KNOB_POSITION_X));
addField(new DecNumber(buffer, offset + 38, 2, CHU_CONTROL_SLD_KNOB_POSITION_Y));
addField(new DecNumber(buffer, offset + 40, 2, CHU_CONTROL_SLD_STEP_WIDTH));
addField(new DecNumber(buffer, offset + 42, 2, CHU_CONTROL_SLD_STEP_COUNT));
addField(new DecNumber(buffer, offset + 44, 2, CHU_CONTROL_SLD_REGION_TOP));
addField(new DecNumber(buffer, offset + 46, 2, CHU_CONTROL_SLD_REGION_BOTTOM));
addField(new DecNumber(buffer, offset + 48, 2, CHU_CONTROL_SLD_REGION_LEFT));
addField(new DecNumber(buffer, offset + 50, 2, CHU_CONTROL_SLD_REGION_RIGHT));
offset += 52;
break;
case 3: // Text field
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_TF_BACKGROUND_1, "MOS"));
addField(new ResourceRef(buffer, offset + 22, CHU_CONTROL_TF_BACKGROUND_2, "MOS"));
addField(new ResourceRef(buffer, offset + 30, CHU_CONTROL_TF_BACKGROUND_3, "MOS"));
addField(new ResourceRef(buffer, offset + 38, CHU_CONTROL_TF_CARET, "BAM"));
addField(new DecNumber(buffer, offset + 46, 2, CHU_CONTROL_TF_ANIMATION_INDEX));
addField(new DecNumber(buffer, offset + 48, 2, CHU_CONTROL_TF_FRAME_INDEX));
addField(new DecNumber(buffer, offset + 50, 2, CHU_CONTROL_TF_CARET_POSITION_X));
addField(new DecNumber(buffer, offset + 52, 2, CHU_CONTROL_TF_CARET_POSITION_Y));
addField(new DecNumber(buffer, offset + 54, 4, CHU_CONTROL_TF_ID));
if (Profile.isEnhancedEdition()) {
addField(new ResourceRef(buffer, offset + 58, CHU_CONTROL_TF_FONT, new String[]{"FNT", "BAM"}));
} else {
addField(new ResourceRef(buffer, offset + 58, CHU_CONTROL_TF_FONT, "BAM"));
}
addField(new Unknown(buffer, offset + 66, 2));
addField(new TextString(buffer, offset + 68, 32, CHU_CONTROL_TF_TEXT));
addField(new DecNumber(buffer, offset + 100, 2, CHU_CONTROL_TF_FIELD_LENGTH));
addField(new Bitmap(buffer, offset + 102, 4, CHU_CONTROL_TF_ALLOWED_CSE, s_case));
offset += 106;
break;
case 5: // Text area
if (Profile.isEnhancedEdition()) {
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_TA_FONT_MAIN, new String[]{"FNT", "BAM"}));
addField(new ResourceRef(buffer, offset + 22, CHU_CONTROL_TA_FONT_INITIALS, new String[]{"FNT", "BAM"}));
} else {
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_TA_FONT_MAIN, "BAM"));
addField(new ResourceRef(buffer, offset + 22, CHU_CONTROL_TA_FONT_INITIALS, "BAM"));
}
addField(new ColorPicker(buffer, offset + 30, CHU_CONTROL_TA_COLOR_1, ColorPicker.Format.RGBX));
addField(new ColorPicker(buffer, offset + 34, CHU_CONTROL_TA_COLOR_2, ColorPicker.Format.RGBX));
addField(new ColorPicker(buffer, offset + 38, CHU_CONTROL_TA_COLOR_3, ColorPicker.Format.RGBX));
addField(new DecNumber(buffer, offset + 42, 4, CHU_CONTROL_TA_SCROLLBAR_ID));
offset += 46;
break;
case 6: // Label
addField(new StringRef(buffer, offset + 14, CHU_CONTROL_LBL_TEXT));
if (Profile.isEnhancedEdition()) {
addField(new ResourceRef(buffer, offset + 18, CHU_CONTROL_LBL_FONT, new String[]{"FNT", "BAM"}));
} else {
addField(new ResourceRef(buffer, offset + 18, CHU_CONTROL_LBL_FONT, "BAM"));
}
addField(new ColorPicker(buffer, offset + 26, CHU_CONTROL_LBL_COLOR_1, ColorPicker.Format.RGBX));
addField(new ColorPicker(buffer, offset + 30, CHU_CONTROL_LBL_COLOR_2, ColorPicker.Format.RGBX));
addField(new Flag(buffer, offset + 34, 2, CHU_CONTROL_LBL_FLAGS, s_label));
offset += 36;
break;
case 7: // Scroll bar
addField(new ResourceRef(buffer, offset + 14, CHU_CONTROL_SB_GRAPHICS, "BAM"));
addField(new DecNumber(buffer, offset + 22, 2, CHU_CONTROL_SB_ANIMATION_INDEX));
addField(new DecNumber(buffer, offset + 24, 2, CHU_CONTROL_SB_FRAME_INDEX_UP_UNPRESSED));
addField(new DecNumber(buffer, offset + 26, 2, CHU_CONTROL_SB_FRAME_INDEX_UP_PRESSED));
addField(new DecNumber(buffer, offset + 28, 2, CHU_CONTROL_SB_FRAME_INDEX_DOWN_UNPRESSED));
addField(new DecNumber(buffer, offset + 30, 2, CHU_CONTROL_SB_FRAME_INDEX_DOWN_PRESSED));
addField(new DecNumber(buffer, offset + 32, 2, CHU_CONTROL_SB_FRAME_INDEX_TROUGH));
addField(new DecNumber(buffer, offset + 34, 2, CHU_CONTROL_SB_FRAME_INDEX_SLIDER));
addField(new DecNumber(buffer, offset + 36, 4, CHU_CONTROL_SB_TEXT_ID));
offset += 40;
break;
default:
HexNumber len = (HexNumber)getAttribute(CHU_CONTROL_LENGTH);
addField(new Unknown(buffer, offset + 14, len.getValue() - 14));
offset += len.getValue();
break;
}
// handling optional gap between controls
if (offset < endOffset) {
addField(new Unknown(buffer, offset, endOffset - offset, COMMON_UNUSED));
offset = endOffset;
}
return offset;
}
public void writeControl(OutputStream os) throws IOException
{
for (int i = 2; i < getFieldCount(); i++)
getField(i).write(os);
}
}