public TilesetEditor(Tileset t) { Gtk.Builder builder = new Builder(); builder.AddFromString(Helper.ReadResourceFile("LynnaLab.Glade.TilesetEditor.ui")); builder.Autoconnect(this); tilesetSpinButtonContainer = (Gtk.Box)builder.GetObject("tilesetSpinButtonContainer"); tilesetVreContainer = (Gtk.Box)builder.GetObject("tilesetVreContainer"); tilesetViewerContainer = (Gtk.Box)builder.GetObject("tilesetViewerContainer"); subTileContainer = (Gtk.Box)builder.GetObject("subTileContainer"); subTileGfxContainer = (Gtk.Box)builder.GetObject("subTileGfxContainer"); paletteEditorContainer = (Gtk.Box)builder.GetObject("paletteEditorContainer"); paletteFrameLabel = (Gtk.Label)builder.GetObject("paletteFrameLabel"); base.Child = (Gtk.Widget)builder.GetObject("TilesetEditor"); tilesetviewer1 = new TilesetViewer(); tilesetviewer1.AddTileSelectedHandler(delegate(object sender, int index) { subTileEditor.SetTileIndex(index); }); tilesetViewerContainer.Add(tilesetviewer1); subTileGfxViewer = new GfxViewer(); subTileGfxViewer.SelectionColor = CairoHelper.ConvertColor(0, 256, 0); subTileGfxViewer.AddTileSelectedHandler(delegate(object sender, int index) { if (subTileEditor != null) { subTileEditor.SubTileIndex = (byte)(index ^ 0x80); } }); subTileGfxContainer.Add(subTileGfxViewer); subTileEditor = new SubTileEditor(this); subTileContainer.Add(subTileEditor); paletteEditor = new PaletteEditor(); paletteEditorContainer.Add(paletteEditor); tilesetSpinButton = new SpinButtonHexadecimal(); tilesetSpinButtonContainer.Add(tilesetSpinButton); SetTileset(t); tilesetSpinButton.ValueChanged += TilesetSpinButtonChanged; tilesetEventWrapper.Bind <int>("TileModifiedEvent", OnTileModified); tilesetEventWrapper.Bind <EventArgs>("PaletteHeaderGroupModifiedEvent", OnPalettesChanged); }
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, 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, 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 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 TreasureEditorGui(PluginManager manager) : base(0.5f,0.0f,0.0f,0.0f) { this.manager = manager; highIndexButton = new SpinButtonHexadecimal(0,0xff); highIndexButton.Digits = 2; highIndexButton.ValueChanged += (a,b) => { SetTreasure(Index); }; Button hAddButton = new Gtk.Button(); hAddButton.Clicked += (a,b) => { Treasure.AddHighIndex(); SetTreasure(0xffff); }; hAddButton.UseStock = true; hAddButton.UseUnderline = true; hAddButton.Image = new Gtk.Image(Gtk.Stock.Add, Gtk.IconSize.Button); Button hRemoveButton = new Gtk.Button(); hRemoveButton.Clicked += (a,b) => { Gtk.MessageDialog d = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Warning, ButtonsType.YesNo, "This will shift the indices for all treasures starting from " + Wla.ToByte((byte)(Index>>8)) + "! All treasures after this WILL BREAK! " + "Are you sure you want to continue?" ); var r = (ResponseType)d.Run(); d.Destroy(); if (r != Gtk.ResponseType.Yes) return; Treasure.RemoveHighIndex(Index>>8); SetTreasure(Index); }; hRemoveButton.UseStock = true; hRemoveButton.UseUnderline = true; hRemoveButton.Image = new Gtk.Image(Gtk.Stock.Remove, Gtk.IconSize.Button); lowIndexButton = new SpinButtonHexadecimal(0,0xff); lowIndexButton.Digits = 2; lowIndexButton.ValueChanged += (a,b) => { SetTreasure(Index); }; Button addButton = new Gtk.Button(); addButton.Clicked += (a,b) => { Treasure.AddSubIndex(Index>>8); SetTreasure((Index&0xff00) + 0xff); }; addButton.UseStock = true; addButton.UseUnderline = true; addButton.Image = new Gtk.Image(Gtk.Stock.Add, Gtk.IconSize.Button); Button removeButton = new Gtk.Button(); removeButton.Clicked += (a,b) => { if ((Index&0xff) < Treasure.GetNumLowIndices(Index>>8)-1) { Gtk.MessageDialog d = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Warning, ButtonsType.YesNo, "This will shift all sub-indices for treasure " + Wla.ToByte((byte)(Index>>8)) + " starting from sub-index " + Wla.ToByte((byte)(Index&0xff)) + "! Are you sure you want to continue?" ); var r = (ResponseType)d.Run(); d.Destroy(); if (r != Gtk.ResponseType.Yes) return; } Treasure.RemoveSubIndex(Index); SetTreasure((Index&0xff00) + 0xff); }; removeButton.UseStock = true; removeButton.UseUnderline = true; removeButton.Image = new Gtk.Image(Gtk.Stock.Remove, Gtk.IconSize.Button); var table = new Table(3,2,false); uint y=0; table.Attach(new Gtk.Label("ID1"), 0, 1, y, y+1); table.Attach(highIndexButton, 1, 2, y, y+1); // Disable high add and remove buttons for now, they're not useful // yet // table.Attach(hAddButton,2,3,y,y+1); // table.Attach(hRemoveButton,3,4,y,y+1); y++; table.Attach(new Gtk.Label("ID2"), 0,1,y,y+1); table.Attach(lowIndexButton, 1,2,y,y+1); table.Attach(addButton,2,3,y,y+1); table.Attach(removeButton,3,4,y,y+1); vrContainer = new Alignment(1.0f,1.0f,1.0f,1.0f); VBox vbox = new VBox(); vbox.Add(table); vbox.Add(vrContainer); Add(vbox); SetTreasure(0); }
public ChestEditorGui(PluginManager m) : base(1.0F,0.0F,1.0F,0.0F) { manager = m; indexSpinButton = new SpinButtonHexadecimal(0,Project.GetNumRooms()-1); indexSpinButton.Digits = 3; indexSpinButton.ValueChanged += (a,b) => { SetRoom(indexSpinButton.ValueAsInt); }; HBox roomIndexBox = new HBox(); roomIndexBox.Add(new Gtk.Label("Room")); roomIndexBox.Add(indexSpinButton); VBox vbox = new VBox(); vbox.Add(roomIndexBox); vrContainer = new Alignment(1.0F, 1.0F, 1.0F, 1.0F); vbox.Add(vrContainer); Alignment buttonAlign = new Alignment(0.5F, 0.5F, 0.0F, 0.2F); buttonAlign.TopPadding = 3; Button syncButton = new Button("Sync Treasure Data"); syncButton.Clicked += (a,b) => { SyncTreasureEditor(); }; buttonAlign.Add(syncButton); vbox.Add(buttonAlign); Add(vbox); }
public MainWindow(string directory) { log.Debug("Beginning Program"); Gtk.Window.DefaultIcon = new Gdk.Pixbuf(Helper.GetResourceStream("LynnaLab.icon.ico")); Gtk.Builder builder = new Builder(); builder.AddFromString(Helper.ReadResourceFile("LynnaLab.Glade.MainWindow.ui")); builder.Autoconnect(this); mainWindow = (builder.GetObject("mainWindow") as Gtk.Window); menubar1 = (Gtk.MenuBar)builder.GetObject("menubar1"); editMenuItem = (Gtk.MenuItem)builder.GetObject("editMenuItem"); actionMenuItem = (Gtk.MenuItem)builder.GetObject("actionMenuItem"); debugMenuItem = (Gtk.MenuItem)builder.GetObject("debugMenuItem"); minimapNotebook = (Gtk.Notebook)builder.GetObject("minimapNotebook"); contextNotebook = (Gtk.Notebook)builder.GetObject("contextNotebook"); worldSpinButton = (Gtk.SpinButton)builder.GetObject("worldSpinButton"); viewObjectsCheckButton = (Gtk.CheckButton)builder.GetObject("viewObjectsCheckButton"); viewWarpsCheckButton = (Gtk.CheckButton)builder.GetObject("viewWarpsCheckButton"); darkenDungeonRoomsCheckbox = (Gtk.CheckButton)builder.GetObject("darkenDungeonRoomsCheckbox"); dungeonSpinButton = (Gtk.SpinButton)builder.GetObject("dungeonSpinButton"); floorSpinButton = (Gtk.SpinButton)builder.GetObject("floorSpinButton"); roomVreHolder = (Gtk.Box)builder.GetObject("roomVreHolder"); chestAddHolder = (Gtk.Box)builder.GetObject("chestAddHolder"); chestEditorBox = (Gtk.Box)builder.GetObject("chestEditorBox"); chestVreHolder = (Gtk.Box)builder.GetObject("chestVreHolder"); treasureVreHolder = (Gtk.Box)builder.GetObject("treasureVreHolder"); nonExistentTreasureHolder = (Gtk.Box)builder.GetObject("nonExistentTreasureHolder"); overallEditingContainer = (Gtk.Box)builder.GetObject("overallEditingContainer"); treasureDataFrame = (Gtk.Widget)builder.GetObject("treasureDataFrame"); treasureDataLabel = (Gtk.Label)builder.GetObject("treasureDataLabel"); editTilesetButton = new Gtk.Button("Edit"); editTilesetButton.Clicked += OnTilesetEditorButtonClicked; roomSpinButton = new SpinButtonHexadecimal(); roomSpinButton.Digits = 3; objectgroupeditor1 = new ObjectGroupEditor(); tilesetViewer1 = new TilesetViewer(); roomeditor1 = new RoomEditor(); worldMinimap = new HighlightingMinimap(); dungeonMinimap = new Minimap(); warpEditor = new WarpEditor(this); statusbar1 = new PriorityStatusbar(); seasonComboBox = new ComboBoxFromConstants(showHelp: false); seasonComboBox.SpinButton.Adjustment.Upper = 3; ((Gtk.Box)builder.GetObject("roomSpinButtonHolder")).Add(roomSpinButton); ((Gtk.Box)builder.GetObject("objectGroupEditorHolder")).Add(objectgroupeditor1); ((Gtk.Box)builder.GetObject("tilesetViewerHolder")).Add(tilesetViewer1); ((Gtk.Box)builder.GetObject("roomEditorHolder")).Add(roomeditor1); ((Gtk.Box)builder.GetObject("worldMinimapHolder")).Add(worldMinimap); ((Gtk.Box)builder.GetObject("dungeonMinimapHolder")).Add(dungeonMinimap); ((Gtk.Box)builder.GetObject("warpEditorHolder")).Add(warpEditor); ((Gtk.Box)builder.GetObject("statusbarHolder")).Add(statusbar1); ((Gtk.Box)builder.GetObject("seasonComboBoxHolder")).Add(seasonComboBox); mainWindow.Title = "LynnaLab " + Helper.ReadResourceFile("LynnaLab.version.txt"); roomeditor1.Scale = 2; roomeditor1.TilesetViewer = tilesetViewer1; roomeditor1.ObjectGroupEditor = objectgroupeditor1; roomeditor1.WarpEditor = warpEditor; eventGroup.Lock(); // Event handlers from widgets roomSpinButton.ValueChanged += eventGroup.Add(OnRoomSpinButtonValueChanged); worldSpinButton.ValueChanged += eventGroup.Add(OnWorldSpinButtonValueChanged); dungeonSpinButton.ValueChanged += eventGroup.Add(OnDungeonSpinButtonValueChanged); floorSpinButton.ValueChanged += eventGroup.Add(OnFloorSpinButtonValueChanged); seasonComboBox.Changed += eventGroup.Add(OnSeasonComboBoxChanged); minimapNotebook.SwitchPage += new SwitchPageHandler(eventGroup.Add <SwitchPageArgs>(OnMinimapNotebookSwitchPage)); contextNotebook.SwitchPage += new SwitchPageHandler(eventGroup.Add <SwitchPageArgs>(OnContextNotebookSwitchPage)); roomeditor1.RoomChangedEvent += eventGroup.Add <RoomChangedEventArgs>((sender, args) => { eventGroup.Lock(); OnRoomChanged(); // Only update minimap if the room editor did a "follow warp". Otherwise, we'll decide // whether to update the minimap from whatever code changed the room. if (args.fromFollowWarp) { UpdateMinimapFromRoom(args.fromFollowWarp); } eventGroup.Unlock(); }); dungeonMinimap.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) { OnMinimapTileSelected(sender, dungeonMinimap.SelectedIndex); })); worldMinimap.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) { OnMinimapTileSelected(sender, worldMinimap.SelectedIndex); })); tilesetViewer1.HoverChangedEvent += eventGroup.Add <int>((sender, tile) => { if (tilesetViewer1.HoveringIndex != -1) { statusbar1.Set((uint)StatusbarMessage.TileHovering, "Hovering Tile: 0x" + tilesetViewer1.HoveringIndex.ToString("X2")); } else { statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering); } }); tilesetViewer1.AddTileSelectedHandler(eventGroup.Add <int>(delegate(object sender, int index) { statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering); statusbar1.Set((uint)StatusbarMessage.TileSelected, "Selected Tile: 0x" + index.ToString("X2")); })); roomeditor1.HoverChangedEvent += eventGroup.Add <int>((sender, tile) => { if (roomeditor1.HoveringIndex != -1) { statusbar1.Set((uint)StatusbarMessage.TileHovering, string.Format( "Hovering Pos: {0},{1} (${1:X}{0:X})", roomeditor1.HoveringX, roomeditor1.HoveringY)); } else { statusbar1.RemoveAll((uint)StatusbarMessage.TileHovering); } }); roomeditor1.WarpDestEditModeChangedEvent += eventGroup.Add <bool>((sender, activated) => { if (activated) { statusbar1.Set((uint)StatusbarMessage.WarpDestEditMode, "Entered warp destination editing mode. To exit this mode, right-click on the warp destination and select \"Done\"."); } else { statusbar1.RemoveAll((uint)StatusbarMessage.WarpDestEditMode); } }); statusbar1.Set((uint)StatusbarMessage.TileSelected, "Selected Tile: 0x00"); OnDarkenDungeonRoomsCheckboxToggled(null, null); // Event handlers from underlying data chestEventWrapper.Bind <ValueModifiedEventArgs>("ModifiedEvent", (sender, args) => UpdateChestData()); chestEventWrapper.Bind <EventArgs>("DeletedEvent", (sender, args) => UpdateChestData()); // Load "plugins" pluginCore = new PluginCore(this); LoadPlugins(); mainWindow.ShowAll(); eventGroup.UnlockAndClear(); overallEditingContainer.Sensitive = false; if (directory != "") { OpenProject(directory); } }