public static string Textbox(Rect rect, string label, string text) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(text); } var id = window.GetID(label); // style var style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.TextBox); // rect rect = window.GetRect(rect); // interact InputTextContext context; text = GUIBehavior.TextBoxBehavior(id, rect, text, out bool hovered, out bool active, out context); // render var state = active ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; GUIAppearance.DrawTextBox(rect, id, text, context, state); style.Restore(); return(text); }
/// <summary> /// Create a horizontal slider that user can drag to select a value. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="label">label</param> /// <param name="value">The value the slider shows.</param> /// <param name="minValue">The value at the top end of the slider.</param> /// <param name="maxValue">The value at the bottom end of the slider.</param> /// <returns>The value set by the user.</returns> /// <remarks>minValue <= value <= maxValue</remarks> public static double Slider(Rect rect, string label, double value, double minValue, double maxValue) { var g = GetCurrentContext(); var window = GetCurrentWindow(); if (window.SkipItems) { return(0); } //get or create the root node var id = window.GetID(label); var container = window.AbsoluteVisualList; var node = (Node)container.Find(visual => visual.Id == id); var text = Utility.FindRenderedText(label); if (node == null) { node = new Node(id, $"Slider<{label}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Slider]); } node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact var spacing = node.RuleSet.Get <double>("ControlLabelSpacing"); var labelWidth = node.RuleSet.Get <double>("LabelWidth"); var sliderWidth = rect.Width - spacing - labelWidth; if (sliderWidth <= 0) { sliderWidth = 1; } var sliderRect = new Rect(node.Rect.X, node.Rect.Y, sliderWidth, node.Rect.Height); bool hovered, held; value = GUIBehavior.SliderBehavior(sliderRect, id, true, value, minValue, maxValue, out hovered, out held); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawSlider(node, text, value, minValue, maxValue, state, sliderRect, labelWidth); return(value); }
bool CloseButton(int id, Rect rect) { Window window = GUI.GetCurrentWindow(); bool pressed = GUIBehavior.ButtonBehavior(rect, id, out bool hovered, out bool held); GUIStyle style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.Button); style.PushBgColor(Color.White, GUIState.Normal); style.PushBgColor(Color.Rgb(232, 17, 35), GUIState.Hover); style.PushBgColor(Color.Rgb(241, 112, 122), GUIState.Active); // Render var d = window.DrawList; var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; var color = style.Get <Color>(GUIStyleName.BackgroundColor, state); d.AddRectFilled(rect, color); Point center = rect.Center; float cross_extent = (15 * 0.7071f) - 1.0f; var fontColor = style.Get <Color>(GUIStyleName.FontColor, state); d.AddLine(center + new Vector(+cross_extent, +cross_extent), center + new Vector(-cross_extent, -cross_extent), fontColor); d.AddLine(center + new Vector(+cross_extent, -cross_extent), center + new Vector(-cross_extent, +cross_extent), fontColor); style.Restore(); return(pressed); }
/// <summary> /// Create an auto-layout button that acts like a toggle. /// </summary> /// <param name="text">text to display on the button</param> /// <param name="selected">whether this selectable is selected</param> /// <param name="options">layout options that specify layouting properties. See also <see cref="GUILayout.Width"/>, <see cref="GUILayout.Height"/>, <see cref="GUILayout.ExpandWidth"/>, <see cref="GUILayout.ExpandHeight"/>, <see cref="GUILayout.StretchWidth"/>, <see cref="GUILayout.StretchHeight"/></param> /// <returns>new value of the toggle-button</returns> public static bool Selectable(string text, bool selected, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } int id = window.GetID(text); // style var style = GUIStyle.Basic; style.ApplySkin(GUIControlName.Selectable); style.ApplyOption(options); // rect Size size = style.CalcSize(text, GUIState.Normal); Rect rect = window.GetRect(id, size); // interact selected = GUIBehavior.SelectableBehavior(rect, id, selected, out bool hovered, out bool held); // render DrawList d = window.DrawList; var state = (selected || (hovered && held)) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; d.DrawBoxModel(rect, text, style, state); style.Restore(); return(selected); }
/// <summary> /// Create an auto-layout horizontal slider that user can drag to select a value. /// </summary> /// <param name="label">label of the slider</param> /// <param name="value">The value the slider shows.</param> /// <param name="minValue">The value at the left end of the slider.</param> /// <param name="maxValue">The value at the right end of the slider.</param> /// <returns>The value set by the user.</returns> /// <remarks>minValue <= value <= maxValue</remarks> public static double Slider(string label, double value, double minValue, double maxValue) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(value); } var id = window.GetID(label); // style apply var style = GUIStyle.Basic; // rect Size size = style.CalcSize(label, GUIState.Normal); style.PushStretchFactor(false, 1);//+1 { var minSilderWidth = 200; size.Width += minSilderWidth; size.Height = 20; } var rect = window.GetRect(id); // interact var spacing = GUISkin.Instance.InternalStyle.Get <double>(GUIStyleName._ControlLabelSpacing); var labelWidth = GUISkin.Instance.InternalStyle.Get <double>(GUIStyleName._LabelWidth); var sliderWidth = rect.Width - spacing - labelWidth; if (sliderWidth <= 0) { sliderWidth = 1; } var sliderRect = new Rect(rect.X, rect.Y, sliderWidth, rect.Height); bool hovered, held; value = GUIBehavior.SliderBehavior(sliderRect, id, true, value, minValue, maxValue, out hovered, out held); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawSlider(rect, label, value, minValue, maxValue, state, sliderRect, labelWidth); // style restore style.PopStyle();//-1 return(value); }
/// <summary> /// Create a button. When the user click it, something will happen immediately. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the button</param> /// <returns>true when the users clicks the button.</returns> public static bool Button(Rect rect, string text) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } int id = window.GetID(text); // style apply var style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.Button); // rect rect = window.GetRect(rect); // interact bool hovered, held; bool pressed = GUIBehavior.ButtonBehavior(rect, id, out hovered, out held, 0); // render var d = window.DrawList; var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; d.DrawBoxModel(rect, text, style, state); style.Restore(); return(pressed); }
/// <summary> /// Create a toggle (check-box) with a label. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="label">label</param> /// <param name="value">Is this toggle checked or unchecked?</param> /// <returns>new value of the toggle</returns> public static bool Toggle(Rect rect, string label, bool value) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } int id = window.GetID(label); // rect rect = window.GetRect(rect); // interact bool hovered; value = GUIBehavior.ToggleBehavior(rect, id, value, out hovered); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawToggle(rect, label, value, state); return(value); }
/// <summary> /// Create an auto-layout button that acts like a toggle. /// </summary> /// <param name="text">text to display on the button</param> /// <param name="selected">whether this selectable is selected</param> /// <param name="options">layout options that specify layouting properties. See also <see cref="GUILayout.Width"/>, <see cref="GUILayout.Height"/>, <see cref="GUILayout.ExpandWidth"/>, <see cref="GUILayout.ExpandHeight"/>, <see cref="GUILayout.StretchWidth"/>, <see cref="GUILayout.StretchHeight"/></param> /// <returns>new value of the toggle-button</returns> public static bool Selectable(string text, bool selected = false, LayoutOptions?options = null) { var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(text); var container = window.RenderTree.CurrentContainer; var node = container.GetNodeById(id); var renderedText = Utility.FindRenderedText(text); if (node == null) { node = new Node(id, $"Selectable<{text}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Selectable]); var size = node.RuleSet.CalcContentBoxSize(text, GUIState.Normal); node.AttachLayoutEntry(size); } container.AppendChild(node); node.ActiveSelf = true; // rect node.Rect = window.GetRect(id); // interact selected = GUIBehavior.SelectableBehavior(node.Rect, id, selected, out bool hovered, out bool held); node.State = selected ? GUIState.Active : GUIState.Normal; if (hovered) { node.State = GUIState.Hover; } if (held) { node.State = GUIState.Active; } // last item state window.TempData.LastItemState = node.State; // render using (var dc = node.RenderOpen()) { dc.DrawBoxModel(renderedText, node.RuleSet, node.Rect); } return(selected); }
/// <summary> /// Create an auto-layout collapsing header. /// </summary> /// <param name="text">header text</param> /// <param name="open">opened</param> /// <param name="options">style options</param> /// <returns>true when opened</returns> /// <remarks> It is always horizontally stretched (factor 1).</remarks> public static bool CollapsingHeader(string text, ref bool open, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node int id = window.GetID(text); var container = window.RenderTree.CurrentContainer; Node node = container.GetNodeById(id); text = Utility.FindRenderedText(text); if (node == null) { //create nodes node = new Node(id, $"CollapsingHeader<{text}>"); node.AttachLayoutEntry(); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.CollapsingHeader]); } node.RuleSet.ApplyOptions(options); node.RuleSet.ApplyOptions(Height(node.RuleSet.GetLineHeight())); node.ActiveSelf = true; container.AppendChild(node); // rect Rect rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(rect, id, out var hovered, out var held, ButtonFlags.PressedOnClick); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; if (pressed) { open = !open; } // last item state window.TempData.LastItemState = node.State; using (var dc = node.RenderOpen()) { dc.DrawBoxModel(node); dc.DrawGlyphRun(node.RuleSet, text, node.ContentRect.TopLeft + new Vector(node.Rect.Height + node.PaddingLeft, 0)); dc.RenderArrow(node.Rect.Min + new Vector(node.PaddingLeft, 0), node.Height, node.RuleSet.FontColor, open ? Direcion.Down : Direcion.Right, 1.0); } return(open); }
/// <summary> /// Create a button that acts like a toggle. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the button</param> /// <param name="selected">whether this selectable is selected</param> /// <returns>new value of the toggle-button</returns> public static bool Selectable(Rect rect, string text, bool selected) { var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(text); var container = window.AbsoluteVisualList; var node = (Node)container.Find(visual => visual.Id == id); var renderedText = Utility.FindRenderedText(text); if (node == null) { node = new Node(id, $"Toggle<{text}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Selectable]); } node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact selected = GUIBehavior.SelectableBehavior(node.Rect, id, selected, out bool hovered, out bool held); node.State = selected ? GUIState.Active : GUIState.Normal; if (hovered) { node.State = GUIState.Hover; } if (held) { node.State = GUIState.Active; } // last item state window.TempData.LastItemState = node.State; // render using (var dc = node.RenderOpen()) { dc.DrawBoxModel(renderedText, node.RuleSet, node.Rect); } return(selected); }
/// <summary> /// Create a single-line text box. /// </summary> /// <param name="label">label</param> /// <param name="width">width</param> /// <param name="text">text</param> /// <param name="flags">filter flags</param> /// <param name="checker">custom checker per char</param> /// <returns>(modified) text</returns> public static string TextBox(string label, double width, string text, InputTextFlags flags, Func <char, bool> checker, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(text); } var id = window.GetID(label); var container = window.RenderTree.CurrentContainer; Node node = container.GetNodeById(id); label = Utility.FindRenderedText(label); if (node == null) { //create node node = new Node(id, $"{nameof(TextBox)}<{label}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.TextBox]); var size = node.RuleSet.CalcContentBoxSize(text, GUIState.Normal); node.AttachLayoutEntry(size); } container.AppendChild(node); node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect Rect rect = window.GetRect(id); // interact InputTextContext context; text = GUIBehavior.TextBoxBehavior(id, rect, text, out bool hovered, out bool active, out context, flags, checker); var state = active ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = state; // render if (flags.HaveFlag(InputTextFlags.Password)) { var dotText = new string('*', text.Length);//FIXME bad performance GUIAppearance.DrawTextBox(node, id, dotText, context, state); } else { GUIAppearance.DrawTextBox(node, id, text, context, state); } return(text); }
public static int ListBox <T>(string label, IReadOnlyList <T> items, int selectedIndex) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(selectedIndex); } int id = window.GetID(label); PushID("ListboxField" + id); var style = GUIStyle.Basic; BeginHorizontal("Field"); BeginVertical("Items", GUILayout.ExpandWidth(true)); { style.Save(); style.ApplySkin(GUIControlName.ListBox); style.PushStretchFactor(false, 1); style.PushCellSpacing(true, 0); for (var i = 0; i < items.Count; i++) { var item = items[i]; string itemText = item.ToString(); var itemId = window.GetID(string.Format("Item_{0}_{1}", i, itemText)); var textSize = style.CalcSize(itemText, GUIState.Normal); var itemRect = window.GetRect(itemId, textSize); bool hovered; bool on = GUIBehavior.ToggleBehavior(itemRect, id, selectedIndex == i, out hovered); if (on) { selectedIndex = i; } var d = window.DrawList; var state = on ? GUIState.Active : GUIState.Normal; d.DrawBoxModel(itemRect, itemText, style, state); } style.Restore(); } EndVertical(); GUILayout.Space("FieldSpacing", GUISkin.Current.FieldSpacing); GUILayout.Label(label, GUILayout.Width((int)GUISkin.Current.LabelWidth)); EndHorizontal(); PopID(); return(selectedIndex); }
/// <summary> /// Create an auto-layout collapsing header. /// </summary> /// <param name="text">header text</param> /// <param name="open">opened</param> /// <param name="options">style options</param> /// <returns>true when opened</returns> /// <remarks> It is always horizontally stretched (factor 1).</remarks> public static bool CollapsingHeader(string text, ref bool open, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node int id = window.GetID(text); var container = window.RenderTree.CurrentContainer; Node node = container.GetNodeById(id); text = Utility.FindRenderedText(text); var displayText = (open ? "-" : "+") + text; if (node == null) { //create nodes node = new Node(id, $"CollapsingHeader<{text}>"); node.AttachLayoutEntry(); container.AppendChild(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.CollapsingHeader]); node.Geometry = new TextGeometry(displayText); } node.RuleSet.ApplyOptions(options); node.RuleSet.ApplyOptions(Height(node.RuleSet.GetLineHeight())); node.ActiveSelf = true; var textPrimitive = node.Geometry as TextGeometry; Debug.Assert(textPrimitive != null); textPrimitive.Text = displayText; // rect Rect rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(rect, id, out var hovered, out var held, ButtonFlags.PressedOnClick); if (pressed) { open = !open; node.State = open ? GUIState.Active : GUIState.Normal; } return(open); }
/// <summary> /// Create an auto-layout toggle (check-box) with an label. /// </summary> /// <param name="label">text to display</param> /// <param name="value">Is this toggle checked or unchecked?</param> /// <returns>new value of the toggle</returns> public static bool Toggle(string label, bool value) { var g = GetCurrentContext(); var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(label); var container = window.RenderTree.CurrentContainer; var node = container.GetNodeById(id); var text = Utility.FindRenderedText(label); if (node == null) { node = new Node(id, $"Toggle<{label}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Toggle]); var size = node.RuleSet.CalcContentBoxSize(text, GUIState.Normal); size.Width += size.Height + node.RuleSet.PaddingLeft; node.AttachLayoutEntry(size); } container.AppendChild(node); node.ActiveSelf = true; // rect node.Rect = window.GetRect(id); // interact value = GUIBehavior.ToggleBehavior(node.Rect, id, value, out var hovered); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawToggle(node, text, value, state); return(value); }
public static bool RadioButton(string label, bool active) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } GUIContext g = GetCurrentContext(); int id = window.GetID(label); // style var style = GUIStyle.Basic; Size label_size = style.CalcSize(label, GUIState.Normal); Rect check_bb = window.GetRect(window.GetID(label + "_check")); Rect text_bb = window.GetRect(id); Rect total_bb = Rect.Union(check_bb, text_bb); Point center = check_bb.Center; center.x = (int)center.x + 0.5f; center.y = (int)center.y + 0.5f; var radius = check_bb.Height * 0.5f; bool hovered, held; bool pressed = GUIBehavior.ButtonBehavior(total_bb, id, out hovered, out held); var d = window.DrawList; var state = ((held && hovered) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal); d.AddCircleFilled(center, (float)radius, ((held && hovered) ? Color.FrameBgActive : hovered ? Color.FrameBgHovered : Color.FrameBg), 16); if (active) { var check_sz = Math.Min(check_bb.Width, check_bb.Height); var pad = Math.Max(1.0f, (int)(check_sz / 6.0f)); d.AddCircleFilled(center, radius - pad, Color.CheckMark, 16); } if (label_size.Width > 0.0f) { d.AddText(text_bb, label, style, state); } return(pressed); }
/// <summary> /// Create a toggle (check-box) with a label. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="label">label</param> /// <param name="value">Is this toggle checked or unchecked?</param> /// <returns>new value of the toggle</returns> public static bool Toggle(Rect rect, string label, bool value) { var g = GetCurrentContext(); var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(label); var container = window.AbsoluteVisualList; var node = (Node)container.Find(visual => visual.Id == id); var text = Utility.FindRenderedText(label); if (node == null) { node = new Node(id, $"Toggle<{label}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Toggle]); } node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact value = GUIBehavior.ToggleBehavior(node.Rect, id, value, out var hovered); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawToggle(node, text, value, state); return(value); }
/// <summary> /// Create an auto-layout button. When the user click it, something will happen immediately. /// </summary> /// <param name="text">text to display on the button</param> /// <param name="options">style options</param> public static bool Button(string text, LayoutOptions?options) { var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(text); var container = window.RenderTree.CurrentContainer; var node = container.GetNodeById(id); text = Utility.FindRenderedText(text); if (node == null) { //create node node = new Node(id, $"Button<{text}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); var size = node.RuleSet.CalcContentBoxSize(text, GUIState.Normal); node.AttachLayoutEntry(size); } container.AppendChild(node); node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect node.Rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = node.State; // draw using (var dc = node.RenderOpen()) { dc.DrawBoxModel(text, node.RuleSet, node.Rect); } return(pressed); }
public static bool ImageButton(string filePath, Size size, Point uv0, Point uv1) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } var id = window.GetID(filePath); // style var style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.Button); // rect var texture = TextureUtil.GetTexture(filePath); if (size == Size.Empty) { size = style.CalcSize(texture, GUIState.Normal); } var rect = window.GetRect(id); if (rect == Layout.StackLayout.DummyRect) { style.Restore(); return(false); } // interact bool hovered, held; bool pressed = GUIBehavior.ButtonBehavior(rect, id, out hovered, out held, 0); // render style.PushUV(uv0, uv1); var d = window.DrawList; var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; d.DrawBoxModel(rect, texture, style, state); style.Restore(); return(pressed); }
public static bool ImageButton(string filePath, Size size, Vector offset) { var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(filePath); var container = window.RenderTree.CurrentContainer; var node = container.GetNodeById(id); if (node == null) { //create node node = new Node(id, $"Button<{filePath}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); node.RuleSet.ObjectPosition = (offset.X, offset.Y); node.AttachLayoutEntry(size); } container.AppendChild(node); node.ActiveSelf = true; // rect node.Rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = node.State; // draw using (var dc = node.RenderOpen()) { var texture = TextureUtil.GetTexture(filePath); dc.DrawBoxModel(texture, node.RuleSet, node.Rect); } return(pressed); }
/// <summary> /// Create a button. When the user click it, something will happen immediately. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the button, optionally incuding the id: "#MyButton"</param> /// <param name="options">style options</param> /// <returns>true when the users clicks the button.</returns> public static bool Button(Rect rect, string text, LayoutOptions?options) { var window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node var id = window.GetID(text); var container = window.AbsoluteVisualList; var node = (Node)container.Find(visual => visual.Id == id); text = Utility.FindRenderedText(text); if (node == null) { //create button node node = new Node(id, $"Button<{text}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); } node.RuleSet.ApplyStack(); node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = node.State; // draw using (var dc = node.RenderOpen()) { dc.DrawBoxModel(text, node.RuleSet, node.Rect); } return(pressed); }
/// <summary> /// Create a horizontal slider that user can drag to select a value. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="label">label</param> /// <param name="value">The value the slider shows.</param> /// <param name="minValue">The value at the top end of the slider.</param> /// <param name="maxValue">The value at the bottom end of the slider.</param> /// <returns>The value set by the user.</returns> /// <remarks>minValue <= value <= maxValue</remarks> public static double Slider(Rect rect, string label, double value, double minValue, double maxValue) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(value); } int id = window.GetID(label); // rect rect = window.GetRect(rect); // interact var spacing = GUISkin.Instance.InternalStyle.Get <double>(GUIStyleName._ControlLabelSpacing); var labelWidth = GUISkin.Instance.InternalStyle.Get <double>(GUIStyleName._LabelWidth); var sliderWidth = rect.Width - spacing - labelWidth; if (sliderWidth <= 0) { sliderWidth = 1; } var sliderRect = new Rect(rect.X, rect.Y, sliderWidth, rect.Height); bool hovered, held; value = GUIBehavior.SliderBehavior(sliderRect, id, true, value, minValue, maxValue, out hovered, out held); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawSlider(rect, label, value, minValue, maxValue, state, sliderRect, labelWidth); return(value); }
/// <summary> /// Create a single-line text box. /// </summary> /// <param name="label">label</param> /// <param name="width">width</param> /// <param name="text">text</param> /// <param name="flags">filter flags</param> /// <param name="checker">custom checker per char</param> /// <returns>(modified) text</returns> public static string TextBox(string label, double width, string text, InputTextFlags flags, Func <char, bool> checker, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(text); } int id = window.GetID(label); // style apply var style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.TextBox); style.ApplyOption(options); // rect var height = style.GetLineHeight(); var size = new Size(width, height); Rect rect = window.GetRect(id, size); // interact InputTextContext context; text = GUIBehavior.TextBoxBehavior(id, rect, text, out bool hovered, out bool active, out context, flags, checker); // render var d = window.DrawList; var state = active ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; if (flags.HaveFlag(InputTextFlags.Password)) { var dotText = new string('*', text.Length);//FIXME bad performance GUIAppearance.DrawTextBox(rect, id, dotText, context, state); } else { GUIAppearance.DrawTextBox(rect, id, text, context, state); } style.Restore(); return(text); }
/// <summary> /// Create an auto-layout button. When the user click it, something will happen immediately. /// </summary> /// <param name="text">text to display on the button</param> /// <param name="options">style options</param> public static bool Button(string text, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node int id = window.GetID(text); var container = window.RenderTree.CurrentContainer; Node node = container.GetNodeById(id); text = Utility.FindRenderedText(text); if (node == null) { //create node node = new Node(id, $"Button<{text}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); var size = node.RuleSet.CalcSize(text, GUIState.Normal); node.AttachLayoutEntry(size); container.AppendChild(node); node.Primitive = new TextPrimitive(text); } node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; var textPrimitive = node.Primitive as TextPrimitive; Debug.Assert(textPrimitive != null); textPrimitive.Text = text; // rect node.Rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; return(pressed); }
/// <summary> /// Create a button. When the user click it, something will happen immediately. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the button, optionally incuding the id: "#MyButton"</param> /// <param name="options">style options</param> /// <returns>true when the users clicks the button.</returns> public static bool Button(Rect rect, string text, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node int id = window.GetID(text); var container = window.AbsoluteVisualList; Node node = (Node)container.Find(visual => visual.Id == id); text = Utility.FindRenderedText(text); if (node == null) { //create button node node = new Node(id, $"Button<{text}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); node.Geometry = new TextGeometry(text); } node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; var textPrimitive = node.Geometry as TextGeometry; Debug.Assert(textPrimitive != null); textPrimitive.Text = text; // rect node.Rect = window.GetRect(rect); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; return(pressed); }
//TODO multiple/single line TextBox public static string TextBox(Rect rect, string label, string text, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(text); } var id = window.GetID(label); var container = window.AbsoluteVisualList; Node node = (Node)container.Find(visual => visual.Id == id); label = Utility.FindRenderedText(label); if (node == null) { //create node node = new Node(id, $"{nameof(TextBox)}<{label}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.TextBox]); container.Add(node); } node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact InputTextContext context; text = GUIBehavior.TextBoxBehavior(id, rect, text, out bool hovered, out bool active, out context); var state = active ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = state; // render GUIAppearance.DrawTextBox(node, id, text, context, state); return(text); }
/// <summary> /// Create an auto-layout toggle (check-box) with an label. /// </summary> /// <param name="label">text to display</param> /// <param name="value">Is this toggle checked or unchecked?</param> /// <returns>new value of the toggle</returns> public static bool Toggle(string label, bool value) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } int id = window.GetID(label); // rect var style = GUIStyle.Basic; var textSize = style.CalcSize(label, GUIState.Normal); var size = new Size(16 + textSize.Width, 16 > textSize.Height ? 16 : textSize.Height); var rect = window.GetRect(id); // interact bool hovered; value = GUIBehavior.ToggleBehavior(rect, id, value, out hovered); // render var state = GUIState.Normal; if (hovered) { state = GUIState.Hover; } if (g.ActiveId == id && Mouse.Instance.LeftButtonState == KeyState.Down) { state = GUIState.Active; } GUIAppearance.DrawToggle(rect, label, value, state); return(value); }
/// <summary> /// Create a button. When the user click it, something will happen immediately. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the button, optionally incuding the id: "#MyButton"</param> /// <returns>true when the users clicks the button.</returns> public static bool Button(Rect rect, string text) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } //get or create the root node int id = window.GetID(text); var container = window.NodeTreeRoot; Node node = container.GetNodeById(id); text = Utility.FindRenderedText(text); if (node == null) { //create button node node = new Node(id, $"Button<{text}>"); container.AppendChild(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); node.Primitive = new TextPrimitive(text); } //TODO check if text changes // rect node.Rect = window.GetRect(rect); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); node.State = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; return(pressed); }
internal static ComboBoxContext comboBoxContext;//TODO move this to Window.storage public static int ComboBox(Rect rect, string[] texts) { var window = GetCurrentWindow(); if (window.SkipItems) { return(comboBoxContext.SelectedIndex); } //get or create the root node var id = window.GetID(texts); var container = window.AbsoluteVisualList; var node = (Node)container.Find(visual => visual.Id == id); if (node == null) { //create button node node = new Node(id, $"Combobox<{texts[0]}..>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.ComboBox]); //set initial states TODO move to shared storage GUI.comboBoxContext = new ComboBoxContext(); GUI.comboBoxContext.Texts = texts; GUI.comboBoxContext.Text = texts[0]; GUI.comboBoxContext.SelectedIndex = 0; } node.RuleSet.ApplyStack(); node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact var pressed = GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); if (pressed) { node.State = GUIState.Active; comboBoxContext.WindowOpened = !comboBoxContext.WindowOpened; } comboBoxContext.Text = comboBoxContext.Texts[comboBoxContext.SelectedIndex]; // last item state window.TempData.LastItemState = node.State; //combo if (comboBoxContext.WindowOpened) { //calculate window rect Rect comboPopupWindowRect; { var maxLength = 0; var maxLengthString = string.Empty; foreach (var s in texts) { if (s.Length <= maxLength) { continue; } maxLength = s.Length; maxLengthString = s; } var size = node.RuleSet.CalcSize(maxLengthString); size.Height *= texts.Length; size += new Vector(100, 100); //TEMP HACK Extend the size a little: otherwise a LayoutException will happen var clientPos = node.Rect.BottomLeft; comboPopupWindowRect = new Rect(clientPos, size); } GUILayout.SetNextWindowPos(comboPopupWindowRect.Location); var clickedIndx = -1; Begin($"##ComboWindow_{node.Name}", comboPopupWindowRect, WindowFlags.Popup | WindowFlags.NoTitleBar | WindowFlags.NoCollapse | WindowFlags.NoMove | WindowFlags.NoResize | WindowFlags.NoScrollbar); { GUILayout.BeginVertical("ComboBox"); for (var i = 0; i < texts.Length; i++) { if (GUILayout.Button(texts[i])) { clickedIndx = i; } } GUILayout.EndVertical(); } End(); if (clickedIndx >= 0) { comboBoxContext.SelectedIndex = clickedIndx; comboBoxContext.WindowOpened = false; node.State = Normal; } } //render using var g = node.RenderOpen(); var ruleSet = node.RuleSet; g.DrawBoxModel(node.RuleSet, node.Rect); g.RenderArrow(node.Rect.Min + new Vector(node.PaddingLeft, 0), node.Height, node.RuleSet.FontColor, Internal.Direcion.Down, 1.0); g.DrawGlyphRun(comboBoxContext.Text, ruleSet.FontSize, ruleSet.FontFamily, ruleSet.FontColor, node.Rect.Min + new Vector(node.Height + ruleSet.PaddingLeft, ruleSet.PaddingTop)); return(comboBoxContext.SelectedIndex); }
/// <summary> /// Create a multi-line text box of fixed size. /// </summary> /// <param name="str_id">id</param> /// <param name="size">fixed size</param> /// <param name="text">text</param> /// <returns>(modified) text</returns> public static string TextBox(string str_id, Size size, string text, LayoutOptions?options) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(text); } var container = window.RenderTree.CurrentContainer; var id = window.GetID(str_id); Node node = container.GetNodeById(id); if (node == null) { //create node node = new Node(id, $"{nameof(TextBox)}<{str_id}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.TextBox]); node.AttachLayoutGroup(true); node.RuleSet.ApplyOptions(GUILayout.Width(size.Width).Height(size.Height)); } var textNodeId = window.GetID($"{nameof(TextBox)}<{str_id}>_Text"); var textNode = node.GetDirectNodeById(textNodeId); if (textNode == null) { textNode = new Node(textNodeId); } var textSize = node.RuleSet.CalcContentBoxSize(text, node.State); textNode.RuleSet.Replace(GUISkin.Current[GUIControlName.TextBox]); textNode.ContentSize = textSize; textNode.ActiveSelf = true; node.AppendChild(textNode); container.AppendChild(node); node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect node.Rect = window.GetRect(node.Id); textNode.Rect = window.GetRect(textNode.Id); // interact text = GUIBehavior.TextBoxBehavior(textNode.Id, textNode.Rect, text, out bool hovered, out bool active, out var context); // render var state = active ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; GUIAppearance.DrawTextBox(textNode, textNode.Id, text, context, state); // draw the box var dc = node.RenderOpen(); dc.DrawBoxModel(node.RuleSet, node.Rect); dc.Close(); // do GUI logic for possible scroll-bars node.OnGUI(); return(text); }
public void FirstUpdate(string name, Size size, ref bool open, double backgroundAlpha, WindowFlags flags, long currentFrame, Window parentWindow) { //short names var form = Form.current; var g = form.uiContext; var w = g.WindowManager; this.Active = true; this.BeginCount = 0; this.ClipRect = Rect.Big; this.LastActiveFrame = currentFrame; var fullScreenRect = new Rect(0, 0, form.ClientSize); if (flags.HaveFlag(WindowFlags.ChildWindow) && !flags.HaveFlag(WindowFlags.ComboBox | WindowFlags.Popup)) { //PushClipRect(parentWindow.ClipRect, true); //ClipRect = GetCurrentClipRect(); } else { //PushClipRect(fullScreenRect, true); //ClipRect = GetCurrentClipRect(); } // (draw outer clip rect for test only here) // determine if window is collapsed if (!flags.HaveFlag(WindowFlags.NoTitleBar) && !flags.HaveFlag(WindowFlags.NoCollapse)) { // Collapse window by double-clicking on title bar if (w.HoveredWindow == this && g.IsMouseHoveringRect(this.TitleBarRect) && Mouse.Instance.LeftButtonDoubleClicked) { this.Collapsed = !this.Collapsed; w.FocusWindow(this); open = !this.Collapsed;//overwrite the open state } } this.Collapsed = !open; //update title bar var titleBarRect = this.TitleBarRect; var windowRounding = (float)this.WindowContainer.RuleSet.Get <double>(GUIStyleName.WindowRounding); if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { //text { // title text var textPrimitive = (TextPrimitive)this.titleBarTitleNode.Primitive; if (textPrimitive.Text != this.Name) { textPrimitive.Text = this.Name; } } } this.ShowWindowClientArea(!this.Collapsed); if (this.Collapsed) { //TODO need to do something here? } else//show and update window client area { if (!flags.HaveFlag(WindowFlags.NoResize) && this.ResizeGripNode == null) { var id = this.GetID("#RESIZE"); var node = new Node(id, "Window_ResizeGrip"); node.Primitive = new PathPrimitive(); this.ResizeGripNode = node; this.AbsoluteVisualList.Add(node); } //resize grip var resizeGripColor = Color.Clear; if (!flags.HaveFlag(WindowFlags.AlwaysAutoResize) && !flags.HaveFlag(WindowFlags.NoResize)) { // Manual resize var br = this.Rect.BottomRight; var resizeRect = new Rect(br - new Vector(windowRounding, windowRounding), br); var resizeId = this.GetID("#RESIZE"); GUIBehavior.ButtonBehavior(resizeRect, resizeId, out var hovered, out var held, ButtonFlags.FlattenChilds); resizeGripColor = held ? this.WindowContainer.RuleSet.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Active) : hovered ? this.WindowContainer.RuleSet.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Hover) : this.WindowContainer.RuleSet.Get <Color>(GUIStyleName.ResizeGripColor); if (hovered || held) { //Mouse.Instance.Cursor = Cursor.NeswResize; } if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position var t = Mouse.Instance.Position - g.ActiveIdClickOffset - this.Position; var newSizeWidth = t.X + resizeRect.Width; var newSizeHeight = t.Y + resizeRect.Height; var resizeSize = new Size(newSizeWidth, newSizeHeight); this.ApplySize(resizeSize); // adjust scroll parameters var contentSize = this.ContentRect.Size; if (contentSize != Size.Zero) { var vH = this.Rect.Height - this.TitleBarHeight - this.WindowContainer.RuleSet.BorderVertical - this.WindowContainer.RuleSet.PaddingVertical; var cH = contentSize.Height; if (cH > vH) { var oldScrollY = this.Scroll.Y; oldScrollY = MathEx.Clamp(oldScrollY, 0, cH - vH); this.Scroll.Y = oldScrollY; } } } } // Render resize grip // (after the input handling so we don't have a frame of latency) if (!flags.HaveFlag(WindowFlags.NoResize)) { var br = this.Rect.BottomRight; var borderBottom = this.WindowContainer.RuleSet.BorderBottom; var borderRight = this.WindowContainer.RuleSet.BorderRight; var primitive = (PathPrimitive)this.ResizeGripNode.Primitive; primitive.PathClear(); primitive.PathLineTo(br + new Vector(-borderRight, -borderBottom)); primitive.PathLineTo(br + new Vector(-borderRight, -windowRounding)); primitive.PathArcFast(br + new Vector(-windowRounding - borderRight, -windowRounding - borderBottom), windowRounding, 0, 3); primitive.PathFill(resizeGripColor); } this.ContentRect = Rect.Zero; } }