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;
}
}
}