using System; using System.Diagnostics.Contracts; using System.Drawing; using System.Text; using ReClassNET.Extensions; using ReClassNET.Memory; using ReClassNET.Project; using ReClassNET.UI; namespace ReClassNET.Nodes { public class EnumNode : BaseNode { public override int MemorySize => (int)Enum.Size; public EnumDescription Enum { get; private set; } = EnumDescription.Default; public override void GetUserInterfaceInfo(out string name, out Image icon) { name = "Enum"; icon = Properties.Resources.B16x16_Button_Enum; } public void ChangeEnum(EnumDescription @enum) { Contract.Requires(@enum != null); Enum = @enum; GetParentContainer()?.ChildHasChanged(this); } /// /// Gets the underlaying node for the enum field. /// /// public BaseNumericNode GetUnderlayingNode() { switch (Enum.Size) { case EnumDescription.UnderlyingTypeSize.OneByte: return new UInt8Node(); case EnumDescription.UnderlyingTypeSize.TwoBytes: return new UInt16Node(); case EnumDescription.UnderlyingTypeSize.FourBytes: return new UInt32Node(); case EnumDescription.UnderlyingTypeSize.EightBytes: return new UInt64Node(); } throw new Exception(); // TODO } public long ReadValueFromMemory(MemoryBuffer memory) { switch (Enum.Size) { case EnumDescription.UnderlyingTypeSize.OneByte: return memory.ReadInt8(Offset); case EnumDescription.UnderlyingTypeSize.TwoBytes: return memory.ReadInt16(Offset); case EnumDescription.UnderlyingTypeSize.FourBytes: return memory.ReadInt32(Offset); case EnumDescription.UnderlyingTypeSize.EightBytes: return memory.ReadInt64(Offset); } throw new Exception(); // TODO } private string GetStringRepresentation(long value) { if (!Enum.UseFlagsMode) { var index = Enum.Values.FindIndex(kv => kv.Value == value); if (index == -1) { return value.ToString(); } return Enum.Values[index].Key; } return GetFlagsStringRepresentation(value); } private string GetFlagsStringRepresentation(long value) { var result = (ulong)value; var values = Enum.Values; var index = values.Count - 1; var retval = new StringBuilder(); var firstTime = true; var saveResult = result; while (index >= 0) { var temp = (ulong)values[index].Value; if (index == 0 && temp == 0) { break; } if ((result & temp) == temp) { result -= temp; if (!firstTime) { retval.Prepend(" | "); } retval.Prepend(values[index].Key); firstTime = false; } index--; } if (result != 0) { return value.ToString(); } if (saveResult == 0) { if (values.Count > 0 && values[0].Value == 0) { return values[0].Key; } return "0"; } return retval.ToString(); } public override Size Draw(ViewInfo view, int x, int y) { if (IsHidden && !IsWrapped) { return DrawHidden(view, x, y); } var origX = x; AddSelection(view, x, y, view.Font.Height); x += TextPadding; x = AddIcon(view, x, y, Icons.Enum, HotSpot.NoneId, HotSpotType.None); x = AddAddressOffset(view, x, y); x = AddText(view, x, y, view.Settings.TypeColor, HotSpot.NoneId, "Enum") + view.Font.Width; if (!IsWrapped) { x = AddText(view, x, y, view.Settings.NameColor, HotSpot.NameId, Name) + view.Font.Width; } x = AddText(view, x, y, view.Settings.ValueColor, HotSpot.NoneId, $"<{Enum.Name}>") + view.Font.Width; x = AddIcon(view, x, y, Icons.Change, 4, HotSpotType.ChangeEnumType) + view.Font.Width; x = AddText(view, x, y, view.Settings.TextColor, HotSpot.NoneId, "=") + view.Font.Width; var value = ReadValueFromMemory(view.Memory); x = AddText(view, x, y, view.Settings.TextColor, HotSpot.NoneId, GetStringRepresentation(value)) + view.Font.Width; x = AddComment(view, x, y); DrawInvalidMemoryIndicatorIcon(view, y); AddContextDropDownIcon(view, y); AddDeleteIcon(view, y); return new Size(x - origX, view.Font.Height); } public override int CalculateDrawnHeight(ViewInfo view) { return IsHidden && !IsWrapped ? HiddenHeight : view.Font.Height; } } }