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 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 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 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); }
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 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); }
/// <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); }
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 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); }
/// <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); }
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; } }
public void FirstUpdate(string name, Size size, ref bool open, double backgroundAlpha, WindowFlags flags, long currentFrame, Window parentWindow) { //short names var g = Application.ImGuiContext; var w = g.WindowManager; this.Active = true; this.BeginCount = 0; this.LastActiveFrame = currentFrame; // update viewport UpdateWindowViewport(this); w.CurrentViewport = Viewport; if (Viewport != null) { Viewport.LastFrameActive = g.FrameCount; } // 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; //window container using (var dc = WindowContainer.RenderOpen()) { dc.DrawBoxModel(WindowContainer); } //update title bar var windowRounding = (float)this.WindowContainer.RuleSet.Get <double>(StylePropertyName.WindowRounding); if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { // background using (var dc = this.titleBar.RenderOpen()) { dc.DrawBoxModel(this.titleBar.RuleSet, this.titleBar.Rect); } //icon using (var dc = titleIcon.RenderOpen()) { dc.DrawImage(@"assets/images/logo.png", this.titleIcon.Rect); } //title using (var dc = titleText.RenderOpen()) { dc.DrawGlyphRun(titleText.RuleSet, this.Name, titleText.Rect.TopLeft); } } this.ShowWindowClientArea(!this.Collapsed); if (!this.Collapsed) { //show and update window client area using (var dc = clientArea.RenderOpen()) { dc.DrawBoxModel(clientArea); } if (!flags.HaveFlag(WindowFlags.NoResize)) { if (this.ResizeGripNode == null) { var id = this.GetID("#RESIZE"); var node = new Node(id, "Window_ResizeGrip"); this.ResizeGripNode = node; this.AbsoluteVisualList.Add(node); } //resize grip this.ResizeGripNode.ActiveSelf = true; var resizeGripColor = Color.Clear; var br = this.Rect.BottomRight; if (!flags.HaveFlag(WindowFlags.AlwaysAutoResize) && !flags.HaveFlag(WindowFlags.NoResize)) { // Manual resize var resizeRect = new Rect( br - new Vector(this.WindowContainer.PaddingLeft + this.WindowContainer.BorderLeft, this.WindowContainer.PaddingBottom + this.WindowContainer.BorderLeft), 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>(StylePropertyName.ResizeGripColor, GUIState.Active) : hovered ? this.WindowContainer.RuleSet.Get <Color>(StylePropertyName.ResizeGripColor, GUIState.Hover) : this.WindowContainer.RuleSet.Get <Color>(StylePropertyName.ResizeGripColor); if (hovered || held) { Mouse.Instance.Cursor = (Cursor.NwseResize); } else { Mouse.Instance.Cursor = (Cursor.Default); } 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); } } // Render resize grip // (after the input handling so we don't have a frame of latency) var borderBottom = this.WindowContainer.RuleSet.BorderBottom; var paddingBottom = this.WindowContainer.RuleSet.PaddingBottom; var borderRight = this.WindowContainer.RuleSet.BorderRight; var paddingRight = this.WindowContainer.RuleSet.PaddingRight; using (var dc = this.ResizeGripNode.RenderOpen()) { var path = new PathGeometry(); var figure = new PathFigure(); var A = br + new Vector(-10 - borderRight - paddingRight, 0); var B = br + new Vector(0, -10 - borderBottom - paddingBottom); figure.StartPoint = A; figure.IsFilled = true; figure.Segments.Add(new LineSegment(B, false)); figure.Segments.Add(new LineSegment(br, false)); figure.Segments.Add(new LineSegment(A, false)); path.Figures.Add(figure); dc.DrawGeometry(new Brush(resizeGripColor), null, path); } } this.ContentRect = Rect.Zero; } }
/// <summary> /// Create an auto-layout collapsing header. /// </summary> /// <param name="text">header text</param> /// <param name="open">opened</param> /// <returns>true when opened</returns> /// <remarks> It is horizontally stretched (factor 1).</remarks> public static bool CollapsingHeader(string text, ref bool open, float scale = 1) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } var id = window.GetID(text); // style apply var style = GUIStyle.Basic; style.PushStretchFactor(false, 1); //+1, always expand width style.PushPadding(2); //4 // rect var height = style.GetLineHeight(); Rect rect = window.GetRect(id, new Size(0, height)); if (rect == Layout.StackLayout.DummyRect) //TODO how shold dummy rect be correctly handled in every control? { style.PopStyle(); //-1 style.PopStyle(4); //-4 return(false); } // interact bool hovered, held; bool pressed = GUIBehavior.ButtonBehavior(rect, id, out hovered, out held, ButtonFlags.PressedOnClick); if (pressed) { open = !open; } // render { DrawList d = window.DrawList; style.PushBgColor(new Color(0.40f, 0.40f, 0.90f, 0.45f), GUIState.Normal); //+1 TODO It's stupid to sprcifiy style like this. There should be a better way to do this. style.PushBgColor(new Color(0.45f, 0.45f, 0.90f, 0.80f), GUIState.Hover); //+1 style.PushBgColor(new Color(0.53f, 0.53f, 0.87f, 0.80f), GUIState.Active); //+1 var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; Color col = style.Get <Color>(GUIStyleName.BackgroundColor, state); d.RenderFrame(rect.Min, rect.Max, col, false, 0); style.PopStyle(3); d.RenderCollapseTriangle(rect.Min, open, rect.Height, Color.Black, scale); rect.X += rect.Height; var delta = rect.Width - rect.Height; if (delta > 0) { rect.Width = delta; } d.DrawText(rect, text, style, state); } // style restore style.PopStyle(); //-1 style.PopStyle(4); //-4 return(open); }
internal static bool DoTreeNode(int id, string text, ref bool open) { Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } window.TempData.LastItemId = id; //get or create the root node var container = window.RenderTree.CurrentContainer; var node = container.GetNodeById(id); text = Utility.FindRenderedText(text); if (node == null) { //create nodes node = new Node(id, $"TreeNode<{text}>"); node.AttachLayoutEntry(); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.TreeNode]); } container.AppendChild(node); var lineHeight = node.RuleSet.GetLineHeight(); node.RuleSet.ApplyOptions(Height(lineHeight)); node.ActiveSelf = true; // rect Rect rect = window.GetRect(id); // interact var pressed = GUIBehavior.ButtonBehavior(rect, id, out var hovered, out var held, ButtonFlags.PressedOnClickRelease); 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.DrawRectangle(new Brush(node.RuleSet.BackgroundColor), null, rect); dc.DrawGlyphRun(node.RuleSet, text, node.ContentRect.TopLeft + new Vector(rect.Height + node.PaddingLeft, 0)); dc.RenderArrow(rect.Min + new Vector(node.RuleSet.PaddingTop, lineHeight * 0.15), node.Height, node.RuleSet.FontColor, open ? Internal.Direcion.Down : Internal.Direcion.Right, 0.7); } if (open) { window.CheckStackSize(id, true); PushID(id); BeginHorizontal("#TreeContent"); Space("Space", 20); BeginVertical("#Items"); var cpId = HashCode.Combine(id, 23); window.CheckStackSize(cpId, true); PushID(cpId); } return(open); }
/// <summary> /// Create a button that will be actived when the mouse is over it. /// </summary> /// <param name="rect">position and size of the control</param> /// <param name="text">text to display on the control</param> /// <returns>whether it is activated (the mouse is over it)</returns> public static bool HoverButton(Rect rect, string text) { 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, $"HoverButton<{text}>"); container.Add(node); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); } node.ActiveSelf = true; // rect node.Rect = window.GetRect(rect); // interact GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); // interact bool result = false; var uiState = Application.ImGuiContext; uiState.KeepAliveID(id); if (hovered) { uiState.SetHoverID(id); if (uiState.ActiveId == 0) { result = true; } } else { if (uiState.ActiveId == id) { uiState.SetActiveID(0); } result = false; } var state = GUI.Normal; if (uiState.ActiveId == id) { state = GUI.Active; } node.State = state; // last item state window.TempData.LastItemState = node.State; // draw using (var dc = node.RenderOpen()) { dc.DrawBoxModel(text, node.RuleSet, node.Rect); } return(result); }
public void Setup(string name, Point position, Size size, ref bool open, double bg_alpha, WindowFlags flags, long current_frame, Window parent_window) { Form form = Form.current; GUIContext g = form.uiContext; WindowManager w = g.WindowManager; this.Active = true; this.BeginCount = 0; this.ClipRect = Rect.Big; this.LastActiveFrame = current_frame; // clear draw list, setup outer clip rect this.DrawList.Clear(); this.DrawList.Init(); Rect fullScreenRect = new Rect(0, 0, form.ClientSize); if (flags.HaveFlag(WindowFlags.ChildWindow) && !flags.HaveFlag(WindowFlags.ComboBox | WindowFlags.Popup)) { this.DrawList.PushClipRect(parent_window.ClipRect, true); this.ClipRect = this.DrawList.GetCurrentClipRect(); } else { this.DrawList.PushClipRect(fullScreenRect, true); this.ClipRect = this.DrawList.GetCurrentClipRect(); } // draw outer clip rect //this.DrawList.AddRect(this.ClipRect.TopLeft, this.ClipRect.BottomRight, Color.Blue);//test only // Collapse window by double-clicking on title bar if (!(flags.HaveFlag(WindowFlags.NoTitleBar)) && !(flags.HaveFlag(WindowFlags.NoCollapse))) { if (w.HoveredWindow == this && g.IsMouseHoveringRect(this.TitleBarRect) && Mouse.Instance.LeftButtonDoubleClicked) { this.Collapsed = !this.Collapsed; w.FocusWindow(this); } } else { this.Collapsed = false; } #region size this.ApplySize(this.FullSize); this.Size = this.Collapsed ? this.TitleBarRect.Size : this.FullSize; #endregion #region position this.Position = new Point((int)this.PosFloat.X, (int)this.PosFloat.Y); if (flags.HaveFlag(WindowFlags.ChildWindow)) { this.Position = this.PosFloat = position; this.Size = this.FullSize = size; // 'size' provided by user passed via BeginChild()->Begin(). } #endregion // Draw window + handle manual resize GUIStyle style = this.Style; GUIStyle titleBarStyle = this.TitleBarStyle; Rect title_bar_rect = this.TitleBarRect; float window_rounding = (float)style.Get <double>(GUIStyleName.WindowRounding); if (this.Collapsed) { // Draw title bar only this.DrawList.AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, new Color(0.40f, 0.40f, 0.80f, 0.50f)); } else { Color resize_col = Color.Clear; double rezie_size = this.Style.Get <double>(GUIStyleName.ResizeGripSize); double resize_corner_size = Math.Max(rezie_size * 1.35, window_rounding + 1.0 + rezie_size * 0.2); if (!flags.HaveFlag(WindowFlags.AlwaysAutoResize) && !flags.HaveFlag(WindowFlags.NoResize)) { // Manual resize var br = this.Rect.BottomRight; Rect resize_rect = new Rect(br - new Vector(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); int resize_id = this.GetID("#RESIZE"); bool hovered, held; GUIBehavior.ButtonBehavior(resize_rect, resize_id, out hovered, out held, ButtonFlags.FlattenChilds); resize_col = held ? style.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Active) : hovered ? style.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Hover) : style.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 new_size_width = t.X + resize_rect.Width; var new_size_height = t.Y + resize_rect.Height; new_size_width = MathEx.Clamp(new_size_width, 330, fullScreenRect.Width); //min size of a window is 145x235 new_size_height = MathEx.Clamp(new_size_height, 150, fullScreenRect.Height); Size resize_size = new Size(new_size_width, new_size_height); this.ApplySize(resize_size); // adjust scroll parameters var contentSize = this.ContentRect.Size; if (contentSize != Size.Zero) { var vH = this.Rect.Height - this.TitleBarHeight - this.Style.BorderVertical - this.Style.PaddingVertical; var cH = contentSize.Height; if (cH > vH) { var oldScrollY = this.Scroll.Y; oldScrollY = MathEx.Clamp(oldScrollY, 0, cH - vH); this.Scroll.Y = oldScrollY; } } } this.Size = this.FullSize; title_bar_rect = this.TitleBarRect; } // Window background Color bg_color = style.BackgroundColor; if (bg_alpha >= 0.0f) { bg_color.A = bg_alpha; } if (bg_color.A > 0.0f) { this.DrawList.AddRectFilled(this.Position + new Vector(0, this.TitleBarHeight), this.Rect.BottomRight, bg_color, window_rounding, flags.HaveFlag(WindowFlags.NoTitleBar) ? 15 : 4 | 8); } // Title bar if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { this.DrawList.AddRectFilled(title_bar_rect.TopLeft, title_bar_rect.BottomRight, w.FocusedWindow == this ? titleBarStyle.Get <Color>(GUIStyleName.BackgroundColor, GUIState.Active) : titleBarStyle.Get <Color>(GUIStyleName.BackgroundColor), window_rounding, 1 | 2); } // Render resize grip // (after the input handling so we don't have a frame of latency) if (!flags.HaveFlag(WindowFlags.NoResize)) { Point br = this.Rect.BottomRight; var borderBottom = this.Style.BorderBottom; var borderRight = this.Style.BorderRight; this.DrawList.PathLineTo(br + new Vector(-resize_corner_size, -borderBottom)); this.DrawList.PathLineTo(br + new Vector(-borderRight, -resize_corner_size)); this.DrawList.PathArcToFast( new Point(br.X - window_rounding - borderRight, br.Y - window_rounding - borderBottom), window_rounding, 0, 3); this.DrawList.PathFill(resize_col); } // Scroll bar if (flags.HaveFlag(WindowFlags.VerticalScrollbar)) { //get content size without clip var contentPosition = this.ContentRect.TopLeft; var contentSize = this.ContentRect.Size; if (contentSize != Size.Zero) { int id = this.GetID("#SCROLLY"); double scrollBarWidth = this.Style.Get <double>(GUIStyleName.ScrollBarWidth); Point scroll_TopLeft = new Point( this.Rect.Right - scrollBarWidth - this.Style.BorderRight - this.Style.PaddingRight, this.Rect.Top + this.TitleBarHeight + this.Style.BorderTop + this.Style.PaddingTop); var sH = this.Rect.Height - this.TitleBarHeight - this.Style.BorderVertical - this.Style.PaddingVertical + (flags.HaveFlag(WindowFlags.NoResize) ? 0 : -resize_corner_size); var vH = this.Rect.Height - this.TitleBarHeight - this.Style.BorderVertical - this.Style.PaddingVertical; Point scroll_BottomRight = scroll_TopLeft + new Vector(scrollBarWidth, sH); Rect bgRect = new Rect(scroll_TopLeft, scroll_BottomRight); var cH = contentSize.Height; var top = this.Scroll.Y * sH / cH; var height = sH * vH / cH; if (height < sH) { // handle mouse click/drag bool held = false; bool hovered = false; bool previously_held = (g.ActiveId == id); GUIBehavior.ButtonBehavior(bgRect, id, out hovered, out held); if (held) { top = Mouse.Instance.Position.Y - bgRect.Y - 0.5 * height; top = MathEx.Clamp(top, 0, sH - height); var targetScrollY = top * cH / sH; this.SetWindowScrollY(targetScrollY); } Point scrollButton_TopLeft = scroll_TopLeft + new Vector(0, top); Point scrllButton_BottomRight = scrollButton_TopLeft + new Vector(scrollBarWidth, height); Rect buttonRect = new Rect(scrollButton_TopLeft, scrllButton_BottomRight); //Draw vertical scroll bar and button { var bgColor = this.Style.Get <Color>(GUIStyleName.ScrollBarBackgroundColor); var buttonColor = this.Style.Get <Color>(GUIStyleName.ScrollBarButtonColor, held ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal); this.DrawList.AddRectFilled(bgRect.TopLeft, buttonRect.TopRight, bgColor); this.DrawList.AddRectFilled(buttonRect.TopLeft, buttonRect.BottomRight, buttonColor); this.DrawList.AddRectFilled(buttonRect.BottomLeft, bgRect.BottomRight, bgColor); } } else { var bgColor = this.Style.Get <Color>(GUIStyleName.ScrollBarBackgroundColor); this.DrawList.AddRectFilled(bgRect.TopLeft, bgRect.BottomRight, bgColor); } } } this.ContentRect = Rect.Zero; } // draw title bar text if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { // title text var state = w.FocusedWindow == this ? GUIState.Active : GUIState.Normal; this.DrawList.DrawBoxModel(title_bar_rect, name, titleBarStyle, state); // close button if (CloseButton(this.GetID("#CLOSE"), new Rect(title_bar_rect.TopRight + new Vector(-45, 0), title_bar_rect.BottomRight))) { open = false; } } // Borders if (flags.HaveFlag(WindowFlags.ShowBorders)) { var state = w.FocusedWindow == this ? GUIState.Active : GUIState.Normal; // window border var borderColor = this.Style.Get <Color>(GUIStyleName.WindowBorderColor, state); this.DrawList.AddRect(this.Position, this.Position + new Vector(this.Size.Width, this.Size.Height), borderColor, window_rounding); // window shadow #if false { var state = w.FocusedWindow == this ? GUIState.Active : GUIState.Normal; var shadowColor = this.Style.Get <Color>(GUIStyleName.WindowShadowColor, state); var shadowWidth = this.Style.Get <double>(GUIStyleName.WindowShadowWidth, state); var d = this.DrawList; //top-left corner d.AddRectFilledGradientTopLeftToBottomRight(this.Rect.TopLeft + new Vector(-shadowWidth, -shadowWidth), this.Rect.TopLeft, Color.Clear, shadowColor); //top d.AddRectFilledGradient(this.Rect.TopLeft + new Vector(0, -shadowWidth), this.Rect.TopRight, Color.Clear, shadowColor); d.AddRectFilledGradient(this.Rect.BottomLeft, this.Rect.BottomRight + new Vector(0, shadowWidth), shadowColor, Color.Clear); } #endif } // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() this.WindowClippedRect = this.Rect; this.WindowClippedRect.Intersect(this.ClipRect); }
/// <summary> /// Create an auto-layout button that will be actived when the mouse is over it. /// </summary> /// <param name="text">text to display on the button</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>whether it is activated (the mouse is over it)</returns> public static bool HoverButton(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 button node node = new Node(id, $"HoverButton<{text}>"); node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); var size = node.RuleSet.CalcContentBoxSize(text, GUIState.Normal); node.AttachLayoutEntry(size); node.UseBoxModel = true; } container.AppendChild(node); node.RuleSet.ApplyOptions(options); node.ActiveSelf = true; // rect node.Rect = window.GetRect(id); // interact GUIBehavior.ButtonBehavior(node.Rect, node.Id, out var hovered, out var held); bool result = false; // interact var uiState = Application.ImGuiContext; uiState.KeepAliveID(id); if (hovered) { uiState.SetHoverID(id); if (uiState.ActiveId == 0) { uiState.SetActiveID(id); result = true; } } else { if (uiState.ActiveId == id) { uiState.SetActiveID(0); } result = false; } var state = GUI.Normal; if (uiState.ActiveId == id) { state = GUI.Active; } node.State = state; // last item state window.TempData.LastItemState = node.State; // draw using (var dc = node.RenderOpen()) { dc.DrawBoxModel(text, node.RuleSet, node.Rect); } return(result); }
/// <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); } //get or create the root node int id = window.GetID(text); var t = window.RenderTree.CurrentContainer; Node node = t.GetNodeById(id); Node backgroundNode = null, textNode = null; if (node == null) { //create button node node = new Node(id, $"Button<{text}>"); t.Add(node); window.IDStack.Push(id); //background var backgroundNodeId = window.GetID("Background"); backgroundNode = new Node(backgroundNodeId, "Background"); backgroundNode.Primitive = new PathPrimitive(); backgroundNode.IsFill = true; //text var textNodeId = window.GetID("Text"); textNode = new Node(textNodeId, "Text"); var textPrimitive = new TextPrimitive(); textPrimitive.Text = text; textNode.Primitive = textPrimitive; node.Add(backgroundNode); node.Add(textNode); window.IDStack.Pop(); } else { backgroundNode = node.GetNodeByName("Background"); textNode = node.GetNodeByName("Text"); } Debug.Assert(backgroundNode != null); Debug.Assert(textNode != null); // rect backgroundNode.Rect = window.GetRect(rect); textNode.Rect = backgroundNode.Rect; var primitive = backgroundNode.Primitive as PathPrimitive; Debug.Assert(primitive != null, nameof(primitive) + " != null"); primitive.PathClear(); primitive.PathRect(backgroundNode.Rect); // style apply var style = GUIStyle.Basic; style.Save(); style.ApplySkin(GUIControlName.Button); // interact bool pressed = GUIBehavior.ButtonBehavior(backgroundNode.Rect, node.Id, out var hovered, out var held, 0); var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; var brush = backgroundNode.Brush; brush.FillColor = style.Get <Color>(GUIStyleName.BackgroundColor, state); var strokeStyle = backgroundNode.StrokeStyle; strokeStyle.Color = style.GetBorderColor(state); style.Restore(); 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); }
public static bool RadioButton(string text, bool active) { 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, $"RadioButton<{text}>"); node.UseBoxModel = true; node.RuleSet.Replace(GUISkin.Current[GUIControlName.Button]); 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); bool pressed = GUIBehavior.ButtonBehavior(node.Rect, id, out var hovered, out var held); node.State = (held && hovered) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; // last item state window.TempData.LastItemState = node.State; using (var d = node.RenderOpen()) { Color backgroundCircleColor; switch (node.State) { case GUIState.Active: backgroundCircleColor = Color.DarkBlue; break; case GUIState.Hover: backgroundCircleColor = Color.Argb(200, 173, 216, 230); break; default: backgroundCircleColor = Color.LightBlue; break; } Point center = new Point(node.Rect.X + node.Height / 2, node.Rect.Y + node.Height / 2); center.x = (int)center.x + 0.3f; center.y = (int)center.y + 0.3f; var radius = node.Rect.Height * 0.3f; d.DrawEllipse(new Brush(backgroundCircleColor), null, center, radius, radius); if (active) { var pad = Math.Max(1.0f, (int)(node.Height * 0.15)); d.DrawEllipse(new Brush(Color.Black), null, center, radius - pad, radius - pad); } if (!string.IsNullOrWhiteSpace(text)) { d.DrawGlyphRun(node.RuleSet, text, node.Rect.Location + new Vector(node.Rect.Height + node.RuleSet.PaddingLeft, 0)); } } return(pressed); }
public static bool TreeNode(string label, ref bool open) { GUIContext g = GetCurrentContext(); Window window = GetCurrentWindow(); if (window.SkipItems) { return(false); } BeginVertical(label + "_Tree"); var id = window.GetID(label); // style apply var style = GUIStyle.Basic; style.PushStretchFactor(false, 1); //+1, always expand width style.PushPadding((1, 1, 1, 5)); //+4 do { // rect var lineHeight = style.GetLineHeight(); Rect rect = window.GetRect(id, new Size(0, lineHeight)); if (rect == Layout.StackLayout.DummyRect) //TODO how shold dummy rect be correctly handled in every control? { break; } // interact bool hovered, held; bool pressed = GUIBehavior.ButtonBehavior(rect, id, out hovered, out held, ButtonFlags.PressedOnClick); if (pressed) { open = !open; } // render { DrawList d = window.DrawList; var state = (hovered && held) ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal; if (hovered || held) { style.PushBgColor(new Color(0.40f, 0.40f, 0.90f, 0.45f), GUIState.Normal); //+1 TODO It's stupid to sprcifiy style like this. There should be a better way to do this. style.PushBgColor(new Color(0.45f, 0.45f, 0.90f, 0.80f), GUIState.Hover); //+1 style.PushBgColor(new Color(0.53f, 0.53f, 0.87f, 0.80f), GUIState.Active); //+1 var color = style.Get <Color>(GUIStyleName.BackgroundColor, state); d.RenderFrame(rect.Min, rect.Max, color, false, 0); style.PopStyle(3); //-3 } d.RenderCollapseTriangle(rect.Min + new Vector(0 + style.PaddingTop, lineHeight * 0.15f), open, lineHeight, Color.White, 0.7); rect.X += rect.Height; var delta = rect.Width - rect.Height; if (delta > 0) { rect.Width = delta; } d.DrawText(rect, label, style, state); } }while(false); // style restore style.PopStyle(); //-1 style.PopStyle(4); //-4 BeginHorizontal("#Content"); Space("Space", 20); BeginVertical("#Items"); return(open); }
public static bool Begin(string name, ref bool open, Point position, Size size, double bg_alpha = 1, WindowFlags flags = WindowFlags.VerticalScrollbar) { Form form = Form.current; GUIContext g = form.uiContext; WindowManager w = g.WindowManager; Debug.Assert(name != null); // Window name required Debug.Assert(g.Initialized); // Forgot to call NewFrame() Debug.Assert(g.FrameCountEnded != g.FrameCount); // Called Render() or EndFrame() and haven't called NewFrame() again yet if (flags.HaveFlag(WindowFlags.NoInputs)) { flags |= WindowFlags.NoMove | WindowFlags.NoResize; } // Find or create Window window = w.FindWindowByName(name) ?? w.CreateWindow(name, position, size, flags); // Check if this is the first call of Begin long current_frame = g.FrameCount; bool first_begin_of_the_frame = (window.LastActiveFrame != current_frame); if (first_begin_of_the_frame) { window.Flags = flags; } else { flags = window.Flags; } // Add to stack Window parent_window = w.WindowStack.Count != 0 ? w.WindowStack[w.WindowStack.Count - 1] : null; w.WindowStack.Add(window); w.CurrentWindow = window; Debug.Assert(parent_window != null || !flags.HaveFlag(WindowFlags.ChildWindow)); // Update known root window (if we are a child window, otherwise window == window->RootWindow) int root_idx; for (root_idx = w.WindowStack.Count - 1; root_idx > 0; root_idx--) { if (!(w.WindowStack[root_idx].Flags.HaveFlag(WindowFlags.ChildWindow))) { break; } } window.RootWindow = w.WindowStack[root_idx]; // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { window.Active = true; window.BeginCount = 0; window.ClipRect = Rect.Big; window.LastActiveFrame = current_frame; // clear draw list, setup outer clip rect window.DrawList.Clear(); window.DrawList.Init(); Rect fullScreenRect = new Rect(0, 0, form.ClientSize); if (flags.HaveFlag(WindowFlags.ChildWindow) && !flags.HaveFlag(WindowFlags.ComboBox | WindowFlags.Popup)) { window.DrawList.PushClipRect(parent_window.ClipRect, true); window.ClipRect = window.DrawList.GetCurrentClipRect(); } else { window.DrawList.PushClipRect(fullScreenRect, true); window.ClipRect = window.DrawList.GetCurrentClipRect(); } // draw outer clip rect //window.DrawList.AddRect(window.ClipRect.TopLeft, window.ClipRect.BottomRight, Color.Blue);//test only // Collapse window by double-clicking on title bar if (!(flags.HaveFlag(WindowFlags.NoTitleBar)) && !(flags.HaveFlag(WindowFlags.NoCollapse))) { if (w.HoveredWindow == window && g.IsMouseHoveringRect(window.TitleBarRect) && Mouse.Instance.LeftButtonDoubleClicked) { window.Collapsed = !window.Collapsed; w.FocusWindow(window); } } else { window.Collapsed = false; } #region size window.ApplySize(window.FullSize); window.Size = window.Collapsed ? window.TitleBarRect.Size : window.FullSize; #endregion #region position window.Position = new Point((int)window.PosFloat.X, (int)window.PosFloat.Y); if (flags.HaveFlag(WindowFlags.ChildWindow)) { window.Position = window.PosFloat = position; window.Size = window.FullSize = size; // 'size' provided by user passed via BeginChild()->Begin(). } #endregion // Draw window + handle manual resize GUIStyle style = window.Style; GUIStyle titleBarStyle = window.TitleBarStyle; Rect title_bar_rect = window.TitleBarRect; float window_rounding = (float)style.Get <double>(GUIStyleName.WindowRounding); if (window.Collapsed) { // Draw title bar only window.DrawList.AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, new Color(0.40f, 0.40f, 0.80f, 0.50f)); } else { Color resize_col = Color.Clear; double rezie_size = window.Style.Get <double>(GUIStyleName.ResizeGripSize); double resize_corner_size = Math.Max(rezie_size * 1.35, window_rounding + 1.0 + rezie_size * 0.2); if (!flags.HaveFlag(WindowFlags.AlwaysAutoResize) && !flags.HaveFlag(WindowFlags.NoResize)) { // Manual resize var br = window.Rect.BottomRight; Rect resize_rect = new Rect(br - new Vector(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); int resize_id = window.GetID("#RESIZE"); bool hovered, held; GUIBehavior.ButtonBehavior(resize_rect, resize_id, out hovered, out held, ButtonFlags.FlattenChilds); resize_col = held ? style.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Active) : hovered?style.Get <Color>(GUIStyleName.ResizeGripColor, GUIState.Hover) : style.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 - window.Position; var new_size_width = t.X + resize_rect.Width; var new_size_height = t.Y + resize_rect.Height; new_size_width = MathEx.Clamp(new_size_width, 330, fullScreenRect.Width);//min size of a window is 145x235 new_size_height = MathEx.Clamp(new_size_height, 150, fullScreenRect.Height); Size resize_size = new Size(new_size_width, new_size_height); window.ApplySize(resize_size); // adjust scroll parameters var contentSize = window.ContentRect.Size; if (contentSize != Size.Zero) { var vH = window.Rect.Height - window.TitleBarHeight - window.Style.BorderVertical - window.Style.PaddingVertical; var cH = contentSize.Height; if (cH > vH) { var oldScrollY = window.Scroll.Y; oldScrollY = MathEx.Clamp(oldScrollY, 0, cH - vH); window.Scroll.Y = oldScrollY; } } } window.Size = window.FullSize; title_bar_rect = window.TitleBarRect; } // Window background Color bg_color = style.BackgroundColor; if (bg_alpha >= 0.0f) { bg_color.A = bg_alpha; } if (bg_color.A > 0.0f) { window.DrawList.AddRectFilled(window.Position + new Vector(0, window.TitleBarHeight), window.Rect.BottomRight, bg_color, window_rounding, flags.HaveFlag(WindowFlags.NoTitleBar) ? 15 : 4 | 8); } // Title bar if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { window.DrawList.AddRectFilled(title_bar_rect.TopLeft, title_bar_rect.BottomRight, w.FocusedWindow == window ? titleBarStyle.Get <Color>(GUIStyleName.BackgroundColor, GUIState.Active) : titleBarStyle.Get <Color>(GUIStyleName.BackgroundColor), window_rounding, 1 | 2); } // Render resize grip // (after the input handling so we don't have a frame of latency) if (!flags.HaveFlag(WindowFlags.NoResize)) { Point br = window.Rect.BottomRight; var borderBottom = window.Style.BorderBottom; var borderRight = window.Style.BorderRight; window.DrawList.PathLineTo(br + new Vector(-resize_corner_size, -borderBottom)); window.DrawList.PathLineTo(br + new Vector(-borderRight, -resize_corner_size)); window.DrawList.PathArcToFast(new Point(br.X - window_rounding - borderRight, br.Y - window_rounding - borderBottom), window_rounding, 0, 3); window.DrawList.PathFill(resize_col); } // Scroll bar if (flags.HaveFlag(WindowFlags.VerticalScrollbar)) { //get content size without clip var contentPosition = window.ContentRect.TopLeft; var contentSize = window.ContentRect.Size; if (contentSize != Size.Zero) { int id = window.GetID("#SCROLLY"); double scrollBarWidth = window.Style.Get <double>(GUIStyleName.ScrollBarWidth); Point scroll_TopLeft = new Point( window.Rect.Right - scrollBarWidth - window.Style.BorderRight - window.Style.PaddingRight, window.Rect.Top + window.TitleBarHeight + window.Style.BorderTop + window.Style.PaddingTop); var sH = window.Rect.Height - window.TitleBarHeight - window.Style.BorderVertical - window.Style.PaddingVertical - resize_corner_size; var vH = window.Rect.Height - window.TitleBarHeight - window.Style.BorderVertical - window.Style.PaddingVertical; Point scroll_BottomRight = scroll_TopLeft + new Vector(scrollBarWidth, sH); Rect bgRect = new Rect(scroll_TopLeft, scroll_BottomRight); var cH = contentSize.Height; var top = window.Scroll.Y * sH / cH; var height = sH * vH / cH; if (height < sH) { // handle mouse click/drag bool held = false; bool hovered = false; bool previously_held = (g.ActiveId == id); GUIBehavior.ButtonBehavior(bgRect, id, out hovered, out held); if (held) { top = Mouse.Instance.Position.Y - bgRect.Y - 0.5 * height; top = MathEx.Clamp(top, 0, sH - height); var targetScrollY = top * cH / sH; window.SetWindowScrollY(targetScrollY); } Point scrollButton_TopLeft = scroll_TopLeft + new Vector(0, top); Point scrllButton_BottomRight = scrollButton_TopLeft + new Vector(scrollBarWidth, height); Rect buttonRect = new Rect(scrollButton_TopLeft, scrllButton_BottomRight); //Draw vertical scroll bar and button { var bgColor = window.Style.Get <Color>(GUIStyleName.ScrollBarBackgroundColor); var buttonColor = window.Style.Get <Color>(GUIStyleName.ScrollBarButtonColor, held ? GUIState.Active : hovered ? GUIState.Hover : GUIState.Normal); window.DrawList.AddRectFilled(bgRect.TopLeft, buttonRect.TopRight, bgColor); window.DrawList.AddRectFilled(buttonRect.TopLeft, buttonRect.BottomRight, buttonColor); window.DrawList.AddRectFilled(buttonRect.BottomLeft, bgRect.BottomRight, bgColor); } } else { var bgColor = window.Style.Get <Color>(GUIStyleName.ScrollBarBackgroundColor); window.DrawList.AddRectFilled(bgRect.TopLeft, bgRect.BottomRight, bgColor); } } } window.ContentRect = Rect.Zero; } // draw title bar text if (!flags.HaveFlag(WindowFlags.NoTitleBar)) { var state = w.FocusedWindow == window ? GUIState.Active : GUIState.Normal; window.DrawList.DrawBoxModel(title_bar_rect, name, titleBarStyle, state); } // Borders if (flags.HaveFlag(WindowFlags.ShowBorders)) { var state = w.FocusedWindow == window ? GUIState.Active : GUIState.Normal; // window border var borderColor = window.Style.Get <Color>(GUIStyleName.WindowBorderColor, state); window.DrawList.AddRect(window.Position, window.Position + new Vector(window.Size.Width, window.Size.Height), borderColor, window_rounding); // window shadow #if false { var state = w.FocusedWindow == window ? GUIState.Active : GUIState.Normal; var shadowColor = window.Style.Get <Color>(GUIStyleName.WindowShadowColor, state); var shadowWidth = window.Style.Get <double>(GUIStyleName.WindowShadowWidth, state); var d = window.DrawList; //top-left corner d.AddRectFilledGradientTopLeftToBottomRight(window.Rect.TopLeft + new Vector(-shadowWidth, -shadowWidth), window.Rect.TopLeft, Color.Clear, shadowColor); //top d.AddRectFilledGradient(window.Rect.TopLeft + new Vector(0, -shadowWidth), window.Rect.TopRight, Color.Clear, shadowColor); d.AddRectFilledGradient(window.Rect.BottomLeft, window.Rect.BottomRight + new Vector(0, shadowWidth), shadowColor, Color.Clear); } #endif } // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() window.WindowClippedRect = window.Rect; window.WindowClippedRect.Intersect(window.ClipRect); } // Inner clipping rectangle { // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. Rect title_bar_rect = window.TitleBarRect; const float border_size = 0; var paddingHorizontal = window.Style.PaddingHorizontal; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. Rect clip_rect = new Rect( new Point(Math.Floor(0.5f + title_bar_rect.Min.X + Math.Max(border_size, Math.Floor(paddingHorizontal * 0.5f))), Math.Floor(0.5f + title_bar_rect.Max.Y + border_size)), new Point(Math.Floor(0.5f + window.Position.X + window.Size.Width - Math.Max(border_size, Math.Floor(paddingHorizontal * 0.5f))), Math.Floor(0.5f + window.Position.Y + window.Size.Height - border_size))); window.DrawList.PushClipRect(clip_rect, true); window.ClipRect = clip_rect; //window.DrawList.AddRect(window.ClipRect.TopLeft, window.ClipRect.BottomRight, Color.Red);//test only } // Clear 'accessed' flag last thing if (first_begin_of_the_frame) { window.Accessed = false; } window.BeginCount++; // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). if (flags.HaveFlag(WindowFlags.ChildWindow)) { Debug.Assert(flags.HaveFlag(WindowFlags.NoTitleBar)); window.Collapsed = parent_window != null && parent_window.Collapsed; } window.StackLayout.Begin(); // Return false if we don't intend to display anything to allow user to perform an early out optimization window.SkipItems = window.Collapsed || !window.Active; return(!window.SkipItems); }