public ValueReferenceEditor(Project p, ValueReferenceGroup vrg, int rows, string frameText = null)
: base(1.0F, 1.0F, 1.0F, 1.0F)
{
Project = p;
valueReferenceGroup = vrg;
maxBounds = new int[valueReferenceGroup.GetNumValueReferences()];
widgetPositions = new Tuple <uint, uint> [maxBounds.Count];
widgets = new Gtk.Widget[maxBounds.Count];
helpButtonContainers = new Gtk.Container[maxBounds.Count];
table = new Gtk.Table(2, 2, false);
uint x = 0, y = 0;
int cnt = 0;
foreach (ValueReference r in valueReferenceGroup.GetValueReferences())
{
int index = cnt;
cnt++;
if (y >= rows)
{
y = 0;
x += 3;
}
widgetPositions[index] = new Tuple <uint, uint>(x, y);
// If it has a ConstantsMapping, use a combobox instead of anything else
if (r.ConstantsMapping != null)
{
ComboBoxFromConstants comboBox = new ComboBoxFromConstants(false);
comboBox.SetConstantsMapping(r.ConstantsMapping);
comboBox.Changed += delegate(object sender, EventArgs e) {
r.SetValue(comboBox.ActiveValue);
OnDataModifiedInternal();
};
dataModifiedExternalEvent += delegate() {
comboBox.ActiveValue = r.GetIntValue();
};
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
table.Attach(comboBox, x + 1, x + 2, y, y + 1);
widgets[index] = comboBox;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
goto loopEnd;
}
// ConstantsMapping == null
switch (r.ValueType)
{
case DataValueType.String:
default:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
Gtk.Entry entry = new Gtk.Entry();
if (!r.Editable)
{
entry.Sensitive = false;
}
dataModifiedExternalEvent += delegate() {
entry.Text = r.GetStringValue();
OnDataModifiedInternal();
};
table.Attach(entry, x + 1, x + 2, y, y + 1);
widgets[index] = entry;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
break;
}
case DataValueType.Byte:
case DataValueType.HalfByte:
byteCase:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
SpinButtonHexadecimal spinButton = new SpinButtonHexadecimal(0, 255);
if (!r.Editable)
{
spinButton.Sensitive = false;
}
if (r.ValueType == DataValueType.HalfByte)
{
spinButton.Digits = 1;
spinButton.Adjustment.Upper = 15;
}
else
{
spinButton.Digits = 2;
}
spinButton.ValueChanged += delegate(object sender, EventArgs e) {
Gtk.SpinButton button = sender as Gtk.SpinButton;
if (maxBounds[index] == 0 || button.ValueAsInt <= maxBounds[index])
{
r.SetValue(button.ValueAsInt);
}
else
{
button.Value = maxBounds[index];
}
OnDataModifiedInternal();
};
dataModifiedExternalEvent += delegate() {
spinButton.Value = r.GetIntValue();
};
table.Attach(spinButton, x + 1, x + 2, y, y + 1);
widgets[index] = spinButton;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
}
break;
case DataValueType.WarpDestIndex:
{
Gtk.Button newDestButton = new Gtk.Button("New\nDestination");
newDestButton.Clicked += delegate(object sender, EventArgs e) {
WarpSourceData warpData = (WarpSourceData)r.Data;
WarpDestGroup destGroup = warpData.GetReferencedDestGroup();
// Check if there's unused destination data
// already
for (int i = 0; i < destGroup.GetNumWarpDests(); i++)
{
WarpDestData destData = destGroup.GetWarpDest(i);
if (destData.GetNumReferences() == 0)
{
Gtk.MessageDialog d = new Gtk.MessageDialog(null,
Gtk.DialogFlags.DestroyWithParent,
Gtk.MessageType.Warning,
Gtk.ButtonsType.YesNo,
"Destination index " + i.ToString("X2") + " is not used by any sources. Use this index?\n\n(\"No\" will create a new destination instead.)");
Gtk.ResponseType response = (Gtk.ResponseType)d.Run();
d.Destroy();
if (response == Gtk.ResponseType.Yes)
{
warpData.SetDestData(destGroup.GetWarpDest(i));
}
else if (response == Gtk.ResponseType.No)
{
warpData.SetDestData(destGroup.AddDestData());
}
break;
}
}
};
table.Attach(newDestButton, x + 2, x + 3, y, y + 2);
}
goto byteCase;
case DataValueType.Word:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
SpinButtonHexadecimal spinButton = new SpinButtonHexadecimal(0, 0xffff);
if (!r.Editable)
{
spinButton.Sensitive = false;
}
spinButton.Digits = 4;
spinButton.ValueChanged += delegate(object sender, EventArgs e) {
Gtk.SpinButton button = sender as Gtk.SpinButton;
if (maxBounds[index] == 0 || button.ValueAsInt <= maxBounds[index])
{
r.SetValue(button.ValueAsInt);
}
else
{
button.Value = maxBounds[index];
}
OnDataModifiedInternal();
};
dataModifiedExternalEvent += delegate() {
spinButton.Value = r.GetIntValue();
};
table.Attach(spinButton, x + 1, x + 2, y, y + 1);
widgets[index] = spinButton;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
}
break;
case DataValueType.ByteBit:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
Gtk.CheckButton checkButton = new Gtk.CheckButton();
checkButton.CanFocus = false;
if (!r.Editable)
{
checkButton.Sensitive = false;
}
checkButton.Toggled += delegate(object sender, EventArgs e) {
Gtk.CheckButton button = sender as Gtk.CheckButton;
r.SetValue(button.Active ? 1 : 0);
OnDataModifiedInternal();
};
dataModifiedExternalEvent += delegate() {
checkButton.Active = r.GetIntValue() == 1;
};
table.Attach(checkButton, x + 1, x + 2, y, y + 1);
widgets[index] = checkButton;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
}
break;
case DataValueType.ByteBits:
case DataValueType.WordBits:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
SpinButtonHexadecimal spinButton = new SpinButtonHexadecimal(0, r.MaxValue);
if (!r.Editable)
{
spinButton.Sensitive = false;
}
spinButton.Digits = (uint)Math.Pow(r.MaxValue, ((double)1) / 16) + 1;
spinButton.ValueChanged += delegate(object sender, EventArgs e) {
Gtk.SpinButton button = sender as Gtk.SpinButton;
if (maxBounds[index] == 0 || button.ValueAsInt <= maxBounds[index])
{
r.SetValue(button.ValueAsInt);
}
else
{
button.Value = maxBounds[index];
}
OnDataModifiedInternal();
};
dataModifiedExternalEvent += delegate() {
spinButton.Value = r.GetIntValue();
};
table.Attach(spinButton, x + 1, x + 2, y, y + 1);
widgets[index] = spinButton;
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
}
break;
case DataValueType.ObjectPointer:
{
table.Attach(new Gtk.Label(r.Name), x + 0, x + 1, y, y + 1);
Gtk.Entry entry = new Gtk.Entry();
if (!r.Editable)
{
entry.Sensitive = false;
}
entry.Changed += delegate(object sender, EventArgs e) {
UpdatePointerTextBox(sender as Gtk.Entry, r);
OnDataModifiedInternal();
};
table.Attach(entry, x + 1, x + 2, y, y + 1);
widgets[index] = entry;
pointerFrame = new Gtk.Frame();
pointerFrame.Label = "Pointer data (possibly shared)";
pointerFrame.BorderWidth = 5;
y++;
table.Attach(pointerFrame, x + 0, x + 2, y, y + 1);
dataModifiedExternalEvent += delegate() {
entry.Text = r.GetStringValue();
UpdatePointerTextBox(entry, r);
};
helpButtonContainers[index] = new Gtk.HBox();
table.Attach(helpButtonContainers[index], x + 2, x + 3, y, y + 1, 0, Gtk.AttachOptions.Fill, 0, 0);
}
break;
}
loopEnd:
y++;
}
table.ColumnSpacing = 6;
if (frameText != null)
{
var frame = new Gtk.Frame(frameText);
frame.Add(table);
this.Add(frame);
}
else
{
this.Add(table);
}
this.ShowAll();
Data lastData = null;
foreach (ValueReference r in valueReferenceGroup.GetValueReferences())
{
if (lastData != r.Data)
{
lastData = r.Data;
r.Data.AddDataModifiedHandler(OnDataModifiedExternal);
// Destroy handler
this.Destroyed += delegate(object sender, EventArgs e) {
r.Data.RemoveDataModifiedHandler(OnDataModifiedExternal);
};
}
}
// Initial values
if (dataModifiedExternalEvent != null)
{
dataModifiedExternalEvent();
}
UpdateHelpButtons();
}