void SetTileset(Tileset t) { if (t == tileset) { return; } tileset = t; tilesetEventWrapper.ReplaceEventSource(tileset); subTileEditor.SetTileset(tileset); if (tileset != null) { subTileGfxViewer.SetGraphicsState(tileset.GraphicsState, 0x2000, 0x3000); } tilesetviewer1.SetTileset(tileset); ValueReferenceGroup vrg = tileset.GetValueReferenceGroup(); if (tilesetVre == null) { tilesetVre = new ValueReferenceEditor(Project, vrg, 8); tilesetVreContainer.Add(tilesetVre); } else { tilesetVre.ReplaceValueReferenceGroup(vrg); } OnPalettesChanged(null, null); tilesetSpinButton.Value = tileset.Index; tilesetSpinButton.Adjustment.Upper = Project.NumTilesets - 1; }
public void SetValueReferences(IList <ValueReference> references) { valueReferenceGroup = new ValueReferenceGroup(references); foreach (ValueReference r in valueReferenceGroup.GetValueReferences()) { r.SetData(this); } }
// ONLY call this function if the new ValueReferenceGroup matches the exact structure of the // old one. If there is any mismatch, a new ValueReferenceEditor should be created instead. // But when the structures do match exactly, this is preferred, so that we don't need to // recreate all of the necessary widgets again. public void ReplaceValueReferenceGroup(ValueReferenceGroup vrg) { RemoveModifiedHandlers(); this.valueReferenceGroup = vrg; AddModifiedHandlers(); // Even if we're not rebuilding the widgets we can at least check for minor changes like // to the "editable" variable for (int i = 0; i < ValueReferenceGroup.Count; i++) { Gtk.Widget w = widgetLists[i][1]; w.Sensitive = ValueReferenceGroup[i].Editable; SetTooltip(i, ValueReferenceGroup[i].Tooltip); } // Initial values if (dataModifiedExternalEvent != null) { dataModifiedExternalEvent(); } UpdateHelpButtons(); }
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(); }
public ValueReferenceEditor(Project p, ValueReferenceGroup vrg, string frameText = null) : this(p, vrg, 50, frameText) { }
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]; 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 (r.ConstantsMapping != null) { ComboBoxFromConstants comboBox = new ComboBoxFromConstants(); comboBox.SetConstantsMapping(r.ConstantsMapping); comboBox.Changed += delegate(object sender, EventArgs e) { r.SetValue(comboBox.ActiveValue); }; 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; 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; 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; } 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; } 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; } break; case DataValueType.ByteBits: { 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)((r.MaxValue+0xf)/0x10); 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; } 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); }; } 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(); }
public ValueReferenceEditor(Project p, ValueReferenceGroup vrg, string frameText=null) : this(p, vrg, 50, frameText) { }
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()]; widgetGrids = new List <Gtk.Grid>(); widgetPositions = new Tuple <int, int> [maxBounds.Count]; widgetLists = new List <IList <Gtk.Widget> >(); Gtk.Box hbox = new Gtk.HBox(); hbox.Spacing = 6; Func <Gtk.Grid> newGrid = () => { Gtk.Grid g = new Gtk.Grid(); g.ColumnSpacing = 6; g.RowSpacing = 2; hbox.Add(g); return(g); }; Gtk.Grid grid = newGrid(); int x = 0, y = 0; // Do not use "foreach" here. The "valueReferenceGroup" may be changed. So, whenever we // access a ValueReference from within an event handler, we must do so though the // "valueReferenceGroup" class variable, and NOT though an alias (like with foreach). for (int tmpCounter = 0; tmpCounter < valueReferenceGroup.Count; tmpCounter++) { int i = tmpCounter; // Variable must be distinct within each closure if (y >= rows) { y = 0; x = 0; grid = newGrid(); } // Each ValueReference may use up to 3 widgets in the grid row Gtk.Widget[] widgetList = new Gtk.Widget[3]; widgetPositions[i] = new Tuple <int, int>(x, y); Action <Gtk.SpinButton> setSpinButtonLimits = (spinButton) => { if (valueReferenceGroup[i].MaxValue < 0x10) { spinButton.Digits = 1; } else if (valueReferenceGroup[i].MaxValue < 0x100) { spinButton.Digits = 2; } else if (valueReferenceGroup[i].MaxValue < 0x1000) { spinButton.Digits = 3; } else { spinButton.Digits = 4; } spinButton.Adjustment.Lower = valueReferenceGroup[i].MinValue; spinButton.Adjustment.Upper = valueReferenceGroup[i].MaxValue; }; int entryWidgetWidth = 1; // If it has a ConstantsMapping, use a combobox instead of anything else if (valueReferenceGroup[i].ConstantsMapping != null) { ComboBoxFromConstants comboBox = new ComboBoxFromConstants(showHelp: true, vertical: true); comboBox.SetConstantsMapping(valueReferenceGroup[i].ConstantsMapping); // Must put this before the "Changed" handler below to avoid // it being fired (for some reason?) setSpinButtonLimits(comboBox.SpinButton); comboBox.Changed += delegate(object sender, EventArgs e) { valueReferenceGroup[i].SetValue(comboBox.ActiveValue); OnDataModifiedInternal(); }; dataModifiedExternalEvent += delegate() { comboBox.ActiveValue = valueReferenceGroup[i].GetIntValue(); }; /* * comboBox.MarginTop = 4; * comboBox.MarginBottom = 4; */ widgetList[0] = new Gtk.Label(valueReferenceGroup[i].Name); widgetList[1] = comboBox; entryWidgetWidth = 2; goto loopEnd; } // ConstantsMapping == null switch (valueReferenceGroup[i].ValueType) { case ValueReferenceType.String: { widgetList[0] = new Gtk.Label(valueReferenceGroup[i].Name); Gtk.Entry entry = new Gtk.Entry(); if (!valueReferenceGroup[i].Editable) { entry.Sensitive = false; } dataModifiedExternalEvent += delegate() { entry.Text = valueReferenceGroup[i].GetStringValue(); OnDataModifiedInternal(); }; widgetList[1] = entry; break; } case ValueReferenceType.Int: { widgetList[0] = new Gtk.Label(valueReferenceGroup[i].Name); SpinButtonHexadecimal spinButton = new SpinButtonHexadecimal(valueReferenceGroup[i].MinValue, valueReferenceGroup[i].MaxValue); if (!valueReferenceGroup[i].Editable) { spinButton.Sensitive = false; } setSpinButtonLimits(spinButton); spinButton.ValueChanged += delegate(object sender, EventArgs e) { Gtk.SpinButton button = sender as Gtk.SpinButton; if (maxBounds[i] == 0 || button.ValueAsInt <= maxBounds[i]) { valueReferenceGroup[i].SetValue(button.ValueAsInt); } else { button.Value = maxBounds[i]; } OnDataModifiedInternal(); }; dataModifiedExternalEvent += delegate() { spinButton.Value = valueReferenceGroup[i].GetIntValue(); }; widgetList[1] = spinButton; } break; case ValueReferenceType.Bool: { widgetList[0] = new Gtk.Label(valueReferenceGroup[i].Name); Gtk.CheckButton checkButton = new Gtk.CheckButton(); checkButton.FocusOnClick = false; if (!valueReferenceGroup[i].Editable) { checkButton.Sensitive = false; } checkButton.Toggled += delegate(object sender, EventArgs e) { Gtk.CheckButton button = sender as Gtk.CheckButton; valueReferenceGroup[i].SetValue(button.Active ? 1 : 0); OnDataModifiedInternal(); }; dataModifiedExternalEvent += delegate() { checkButton.Active = valueReferenceGroup[i].GetIntValue() == 1; }; widgetList[1] = checkButton; } break; } loopEnd: grid.Attach(widgetList[0], x, y, 1, 1); grid.Attach(widgetList[1], x + 1, y, entryWidgetWidth, 1); widgetList[2] = new Gtk.Alignment(0, 0.5f, 0, 0); // Container for help button widgetList[2].Hexpand = true; // Let this absorb any extra space grid.Attach(widgetList[2], x + 2, y, 1, 1); widgetGrids.Add(grid); widgetLists.Add(widgetList); if (valueReferenceGroup[i].Tooltip != null) { SetTooltip(i, valueReferenceGroup[i].Tooltip); } y++; } if (frameText != null) { var frame = new Gtk.Frame(frameText); frame.Add(hbox); this.Add(frame); } else { this.Add(hbox); } this.ShowAll(); // Initial values if (dataModifiedExternalEvent != null) { dataModifiedExternalEvent(); } UpdateHelpButtons(); AddModifiedHandlers(); this.Destroyed += (sender, args) => RemoveModifiedHandlers(); }
public void SetValueReferences(IList<ValueReference> references) { valueReferenceGroup = new ValueReferenceGroup(references); foreach (ValueReference r in valueReferenceGroup.GetValueReferences()) r.SetData(this); }
public override void Clicked() { Box tmpBox, tmpBox2; Alignment tmpAlign; Box vbox = new Gtk.VBox(); vbox.Spacing = 3; Box hbox = new Gtk.HBox(); hbox.Spacing = 3; Box dungeonVreContainer = new Gtk.VBox(); Box roomVreContainer = new Gtk.VBox(); ValueReferenceEditor dungeonVre = null; ValueReferenceEditor roomVre = null; Alignment frame = new Alignment(0,0,0,0); var dungeonSpinButton = new SpinButton(0,15,1); var floorSpinButton = new SpinButton(0,15,1); var roomSpinButton = new SpinButtonHexadecimal(0,255,1); roomSpinButton.Digits = 2; Minimap minimap = null; System.Action RoomChanged = () => { Dungeon dungeon = minimap.Map as Dungeon; Room room = minimap.GetRoom(); roomSpinButton.Value = room.Index&0xff; var vrs = new List<ValueReference>(); vrs.Add(new StreamValueReference("Up", room.Index&0xff, 0,0, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Right", room.Index&0xff, 1,1, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Down", room.Index&0xff, 2,2, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Left", room.Index&0xff, 3,3, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Key", room.Index&0xff, 4,4, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Chest", room.Index&0xff, 5,5, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Boss", room.Index&0xff, 6,6, DataValueType.ByteBit)); vrs.Add(new StreamValueReference("Dark", room.Index&0xff, 7,7, DataValueType.ByteBit)); Stream stream = Project.GetBinaryFile("rooms/group" + dungeon.Group + "DungeonProperties.bin"); foreach (StreamValueReference r in vrs) r.SetStream(stream); if (roomVre != null) roomVreContainer.Remove(roomVre); var vrg = new ValueReferenceGroup(vrs); roomVre = new ValueReferenceEditor(Project, vrg, 4, "Minimap Data"); roomVreContainer.Add(roomVre); }; System.Action DungeonChanged = () => { Dungeon dungeon = Project.GetIndexedDataType<Dungeon>(dungeonSpinButton.ValueAsInt); floorSpinButton.Adjustment.Upper = dungeon.NumFloors-1; if (floorSpinButton.ValueAsInt >= dungeon.NumFloors) floorSpinButton.Value = dungeon.NumFloors-1; var vrs = new List<ValueReference>(); vrs.Add(new ValueReference("Group", 0, DataValueType.String, false)); vrs.Add(new ValueReference("Wallmaster dest room", 0, DataValueType.Byte)); vrs.Add(new ValueReference("Bottom floor layout", 0, DataValueType.Byte, false)); vrs.Add(new ValueReference("# of floors", 0, DataValueType.Byte, false)); vrs.Add(new ValueReference("Base floor name", 0, DataValueType.Byte)); vrs.Add(new ValueReference("Floors unlocked with compass", 0, DataValueType.Byte)); Data data = dungeon.DataStart; foreach (ValueReference r in vrs) { r.SetData(data); data = data.NextData; } // Remove last ValueReferenceEditor if (dungeonVre != null) dungeonVreContainer.Remove(dungeonVre); var vrg = new ValueReferenceGroup(vrs); dungeonVre = new ValueReferenceEditor(Project, vrg, "Base Data"); dungeonVre.AddDataModifiedHandler(() => { floorSpinButton.Adjustment.Upper = dungeon.NumFloors; minimap.GenerateImage(); RoomChanged(); }); // Replace the "group" option with a custom widget for finer // control. SpinButton groupSpinButton = new SpinButton(4,5,1); groupSpinButton.Value = dungeon.Group; groupSpinButton.ValueChanged += (c,d) => { vrg.SetValue("Group", ">wGroup" + groupSpinButton.ValueAsInt + "Flags"); }; dungeonVre.ReplaceWidget(0, groupSpinButton); dungeonVre.ShowAll(); // Tooltips dungeonVre.AddTooltip(0, "Also known as the high byte of the room index."); dungeonVre.AddTooltip(1, "The low byte of the room index wallmasters will send you to."); dungeonVre.AddTooltip(2, "The index of the layout for the bottom floor. Subsequent floors will use subsequent indices."); dungeonVre.AddTooltip(4, "Determines what the game will call the bottom floor. For a value of:\n$00: The bottom floor is 'B3'.\n$01: The bottom floor is 'B2'.\n$02: The bottom floor is 'B1'.\n$03: The bottom floor is 'F1'."); dungeonVre.AddTooltip(5, "A bitset of floors that will appear on the map when the compass is obtained.\n\nEg. If this is $05, then floors 0 and 2 will be unlocked (bits 0 and 2 are set)."); dungeonVreContainer.Add(dungeonVre); minimap.SetMap(dungeon); minimap.Floor = floorSpinButton.ValueAsInt; RoomChanged(); }; dungeonSpinButton.ValueChanged += (a,b) => { DungeonChanged(); }; floorSpinButton.ValueChanged += (a,b) => { DungeonChanged(); }; frame.Add(vbox); tmpBox = new Gtk.HBox(); tmpBox.Add(new Gtk.Label("Dungeon ")); tmpBox.Add(dungeonSpinButton); tmpBox.Add(new Gtk.Label("Floor ")); tmpBox.Add(floorSpinButton); tmpAlign = new Alignment(0,0,0,0); tmpAlign.Add(tmpBox); vbox.Add(tmpAlign); vbox.Add(hbox); // Leftmost column tmpBox = new VBox(); tmpBox.Add(dungeonVreContainer); var addFloorButton = new Button("Add Floor"); addFloorButton.Image = new Gtk.Image(Gtk.Stock.Add, Gtk.IconSize.Button); addFloorButton.Clicked += (a,b) => { Dungeon dungeon = minimap.Map as Dungeon; int newFloorIndex = dungeon.FirstLayoutIndex + dungeon.NumFloors; // Shift all subsequent layouts 64 bytes down in the data file Stream layoutFile = Project.GetBinaryFile("rooms/dungeonLayouts.bin"); layoutFile.SetLength(layoutFile.Length+64); for (int i=(int)layoutFile.Length/64-1; i>newFloorIndex; i--) { var buf = new byte[64]; layoutFile.Position = (i-1)*64; layoutFile.Read(buf, 0, 64); layoutFile.Write(buf, 0, 64); } // Clear the new floor layoutFile.Position = newFloorIndex*64; for (int j=0;j<64;j++) layoutFile.WriteByte(0); // Shift each dungeon's "FirstLayoutIndex" to match the shifted layouts. for (int i=0; i<Project.GetNumDungeons(); i++) { Dungeon d2 = Project.GetIndexedDataType<Dungeon>(i); if (d2.FirstLayoutIndex >= newFloorIndex) d2.FirstLayoutIndex++; } dungeon.NumFloors = dungeon.NumFloors+1; floorSpinButton.Value = dungeon.NumFloors-1; DungeonChanged(); }; tmpAlign = new Gtk.Alignment(0.5f,0,0,0); tmpAlign.Add(addFloorButton); tmpBox.PackStart(tmpAlign); var removeFloorButton = new Button("Remove Top Floor"); removeFloorButton.Image = new Gtk.Image(Gtk.Stock.Remove, Gtk.IconSize.Button); removeFloorButton.Clicked += (a,b) => { Dungeon dungeon = minimap.Map as Dungeon; if (dungeon.NumFloors <= 1) return; Gtk.MessageDialog d = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Warning, ButtonsType.YesNo, "Are you quite certain that you wish to delete the top floor of this dungeon?"); var response = (ResponseType)d.Run(); d.Destroy(); if (response == Gtk.ResponseType.Yes) { int deletedFloorIndex = dungeon.FirstLayoutIndex + dungeon.NumFloors-1; // Shift all subsequent layouts 64 bytes up in the data file Stream layoutFile = Project.GetBinaryFile("rooms/dungeonLayouts.bin"); for (int i=deletedFloorIndex; i<layoutFile.Length/64-1; i++) { var buf = new byte[64]; layoutFile.Position = (i+1)*64; layoutFile.Read(buf, 0, 64); layoutFile.Position = i*64; layoutFile.Write(buf, 0, 64); } layoutFile.SetLength(layoutFile.Length-64); // Shift each dungeon's "FirstLayoutIndex" to match the shifted layouts. for (int i=0; i<Project.GetNumDungeons(); i++) { Dungeon d2 = Project.GetIndexedDataType<Dungeon>(i); if (d2.FirstLayoutIndex > deletedFloorIndex) d2.FirstLayoutIndex--; } dungeon.NumFloors = dungeon.NumFloors-1; DungeonChanged(); } }; tmpAlign = new Gtk.Alignment(0.5f,0,0,0); tmpAlign.Add(removeFloorButton); tmpBox.PackStart(tmpAlign); hbox.PackStart(tmpBox); // Middle column (minimap) minimap = new Minimap(); minimap.TileSelectedEvent += (sender) => { RoomChanged(); }; hbox.PackStart(minimap); // Rightmost column tmpAlign = new Alignment(0,0,0,0); tmpAlign.Add(roomVreContainer); tmpBox2 = new HBox(); tmpBox2.Add(new Gtk.Label("Room ")); roomSpinButton.ValueChanged += (a,b) => { (minimap.Map as Dungeon).SetRoom(minimap.SelectedX, minimap.SelectedY, minimap.Floor, roomSpinButton.ValueAsInt); minimap.GenerateImage(); RoomChanged(); }; tmpBox2.Add(roomSpinButton); tmpBox = new VBox(); tmpBox.Add(tmpBox2); tmpBox.Add(tmpAlign); hbox.PackStart(tmpBox); Window w = new Window(null); w.Add(frame); w.ShowAll(); Map map = manager.GetActiveMap(); if (map is Dungeon) dungeonSpinButton.Value = map.Index; DungeonChanged(); }
public void SetTreasure(int index) { int hIndex = index>>8; int lIndex = index&0xff; int hMax = Treasure.GetNumHighIndices(); if (hIndex >= hMax) hIndex = hMax-1; int lMax = Treasure.GetNumLowIndices(hIndex); if (lIndex >= lMax) lIndex = lMax-1; highIndexButton.Adjustment.Upper = hMax-1; lowIndexButton.Adjustment.Upper = lMax-1; highIndexButton.Value = hIndex; lowIndexButton.Value = lIndex; index = hIndex<<8|lIndex; vrContainer.Remove(vrEditor); Data data = Treasure.GetTreasureDataBase(index); ValueReference v1 = new ValueReference("Spawn Mode", 0, 4,6, DataValueType.ByteBits); v1.SetData(data); ValueReference v5 = new ValueReference("Grab Mode", 0, 0,2, DataValueType.ByteBits); v5.SetData(data); ValueReference v6 = new ValueReference("Unknown", 0, 3,3, DataValueType.ByteBit); v6.SetData(data); data = data.NextData; ValueReference v2 = new ValueReference("Parameter", 0, DataValueType.Byte); v2.SetData(data); data = data.NextData; ValueReference v3 = new ValueReference("Text ID", 0, DataValueType.Byte); v3.SetData(data); data = data.NextData; ValueReference v4 = new ValueReference("Gfx", 0, DataValueType.Byte); v4.SetData(data); data = data.NextData; // Byte 1 is sometimes set to 0x80 for unused treasures? v1.SetValue(v1.GetIntValue()&0x7f); ValueReferenceGroup vrGroup = new ValueReferenceGroup(new ValueReference[] {v1, v5, v6, v2, v3, v4}); var vr = new ValueReferenceEditor( Project, vrGroup, "Data"); vr.SetMaxBound(0, 0x7f); // Max bound for Spawn Mode vr.AddDataModifiedHandler(() => { if (TreasureChangedEvent != null) TreasureChangedEvent(); }); vrEditor = vr; vrContainer.Add(vrEditor); if (TreasureChangedEvent != null) TreasureChangedEvent(); }
public void SetRoom(int room) { indexSpinButton.Value = room; vrContainer.Remove(vrEditor); vrEditor = null; v1 = null; v2 = null; v3 = null; v4 = null; Data data = Chest.GetChestData(room); if (data == null) { VBox vbox = new VBox(); Button addButton = new Button("Add"); addButton.Clicked += (a,b) => { Chest.AddChestData(RoomIndex); SetRoom(RoomIndex); }; addButton.Label = "gtk-add"; addButton.UseStock = true; var l = new Gtk.Label("No chest data\nexists for this room."); vbox.Add(l); var btnAlign = new Alignment(0.5f,0.5f,0.0f,0.2f); btnAlign.TopPadding = 3; btnAlign.Add(addButton); vbox.Add(btnAlign); vrEditor = vbox; } else { v1 = new ValueReference("YX", 0, DataValueType.Byte); v1.SetData(data); data = data.NextData; v2 = new ValueReference("Room", 0, DataValueType.Byte, false); v2.SetData(data); data = data.NextData; v3 = new ValueReference("ID1", 0, DataValueType.Byte); v3.SetData(data); data = data.NextData; v4 = new ValueReference("ID2", 0, DataValueType.Byte); v4.SetData(data); data = data.NextData; ValueReferenceGroup vrGroup = new ValueReferenceGroup(new ValueReference[] {v1, v2, v3, v4}); var vr = new ValueReferenceEditor( Project, vrGroup, "Data"); vr.SetMaxBound(0, 0xfe); // Max bound for YX vr.AddDataModifiedHandler(() => { if (ChestChangedEvent != null) ChestChangedEvent(); }); VBox vbox = new VBox(); vbox.Add(vr); Button delButton = new Button("Remove"); delButton.Clicked += (a,b) => { Chest.DeleteChestData(RoomIndex); SetRoom(RoomIndex); }; delButton.Label = "gtk-delete"; delButton.UseStock = true; Alignment btnAlign = new Alignment(0.5f,0.5f,0.0f,0.2f); btnAlign.TopPadding = 3; btnAlign.Add(delButton); vbox.Add(btnAlign); vrEditor = vbox; } if (ChestChangedEvent != null) ChestChangedEvent(); vrContainer.Add(vrEditor); vrContainer.ShowAll(); }