<|start_filename|>gui4opengl/Controls/Slider.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class Slider : UIContainer
    {
        #region Variables
        private int min = 0, max = 10, value = 0;
        private Button sliderButton;
        private bool sliderMouseDown = false;
        private int sliderDown = -1;
        #endregion

        #region Properties
        /// <summary>
        /// The minimum value that the slider can return.
        /// </summary>
        public int Minimum
        {
            get { return min; }
            set
            {
                if (value < 0 || value >= max) throw new ArgumentOutOfRangeException("Minimum");
                min = value;
                if (Value < min) Value = min;
            }
        }

        /// <summary>
        /// The maximum value that the slider can return.
        /// </summary>
        public int Maximum
        {
            get { return max; }
            set
            {
                if (value < 0 || value <= min) throw new ArgumentOutOfRangeException("Maximum");
                max = value;
                if (Value > max) Value = max;
            }
        }

        /// <summary>
        /// The current value of the slider (rounded to the closest integer).
        /// </summary>
        public int Value
        {
            get { return value; }
            set
            {
                if (value < min || value > max) throw new ArgumentOutOfRangeException("Value");
                if (value != this.value && OnValueChanged != null) OnValueChanged(this, new MouseEventArgs());

                this.value = value;

                int x = (int)((value - min) * (Size.X - sliderButton.Size.X) / (max - min));
                sliderButton.Position = new Point(x, 0);
                sliderButton.OnResize();    // we've moved this UIElement, make sure we update the CorrectedPosition, etc
            }
        }

        /// <summary>
        /// Locks the slider to the steps defined by Minimum and Maximum.
        /// This, for example, will cause the slider to 'jump' to the next valid value.
        /// </summary>
        public bool LockToSteps { get; set; }

        /// <summary>
        /// An event that is fired when the value of the slider changes.
        /// </summary>
        public OnMouse OnValueChanged { get; set; }
        #endregion

        #region Constructor
        /// <summary>
        /// Creates a slider with a given texture, minimum, maximum and default values.
        /// </summary>
        /// <param name="sliderTexture">The texture to apply to the slider.  This also defines the slider size.</param>
        /// <param name="min">The minimum value of the slider.</param>
        /// <param name="max">The maximum value of the slider.</param>
        /// <param name="value">The default value of the slider.</param>
        public Slider(Texture sliderTexture, int min = 0, int max = 10, int value = 0)
            : base(new Point(0, 0), new Point(200, sliderTexture.Size.Height), "Slider" + UserInterface.GetUniqueElementID())
        {
            this.min = min;
            this.max = max;
            this.value = value;

            sliderButton = new Button(sliderTexture);
            sliderButton.BackgroundColor = new Vector4(0, 0, 0, 0);

            sliderButton.OnMouseUp = (sender, eventArgs) => sliderMouseDown = false;
            sliderButton.OnMouseDown = (sender, eventArgs) =>
            {
                sliderMouseDown = (eventArgs.Button == MouseButton.Left);
                sliderDown = eventArgs.Location.X;
            };
            sliderButton.OnMouseMove = (sender, eventArgs) => this.OnMouseMove(sender, eventArgs);
            this.OnMouseMove = (sender, eventArgs) =>
            {
                if (!sliderMouseDown) return;

                if (eventArgs.Location.X < CorrectedPosition.X)
                {
                    // handle case where the mouse has gone too far to the left
                    sliderButton.Position = new Point(0, 0);
                    this.Value = Minimum;
                }
                else if (eventArgs.Location.X > CorrectedPosition.X + Size.X)
                {
                    // handle case where the mouse has gone too far to the right
                    sliderButton.Position = new Point(Size.X - sliderButton.Size.X, 0);
                    this.Value = Maximum;
                }
                else
                {
                    int dx = eventArgs.Location.X - sliderDown;

                    int x = eventArgs.Location.X - CorrectedPosition.X - (sliderButton.Size.X / 2);
                    double percent = Math.Max(0, (double)x / (Size.X - sliderButton.Size.X));

                    // take care of locking to the closest step
                    if (LockToSteps) x = (int)(Math.Round(percent * (Maximum - Minimum)) * (Size.X - sliderButton.Size.X) / (Maximum - Minimum));
                    else x = Math.Max(0, Math.Min(Size.X - sliderButton.Size.X, x));

                    if (x == sliderButton.Position.X) return;
                    sliderButton.Position = new Point(x, 0);

                    sliderDown = eventArgs.Location.X;

                    int clampedValue = Math.Max(Minimum, Math.Min(Maximum, (int)Math.Round((Maximum - Minimum) * percent) + Minimum));

                    if (this.value != clampedValue)
                    {
                        this.value = clampedValue;
                        if (OnValueChanged != null) OnValueChanged(this, new MouseEventArgs());
                    }
                }
                sliderButton.OnResize();
            };

            sliderButton.RelativeTo = Corner.BottomLeft;
            sliderButton.Position = new Point(value * (Size.X - sliderButton.Size.X) / (max - min), 0);
            this.AddElement(sliderButton);
        }
        #endregion
    }
}


<|start_filename|>Examples/Example5/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example5
{
    static class Program
    {
        private static Texture sliderTexture;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 5", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create a slider with a specified texture
            sliderTexture = new Texture("data/slider.png");

            OpenGL.UI.Slider slider = new OpenGL.UI.Slider(sliderTexture);
            slider.RelativeTo = OpenGL.UI.Corner.Center;
            slider.BackgroundColor = new Vector4(0.1f, 0.1f, 0.1f, 1f);
            slider.LockToSteps = true;

            // create some text that will change with the slider position
            OpenGL.UI.Text text = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._16pt, "Value: 0");
            text.RelativeTo = OpenGL.UI.Corner.Center;
            text.Position = new Point(120, -text.TextSize.Y / 2);

            slider.OnValueChanged = (sender, e) => text.String = string.Format("Value: {0}", slider.Value);

            // add both the slider and text controls to the UI
            OpenGL.UI.UserInterface.AddElement(slider);
            OpenGL.UI.UserInterface.AddElement(text);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            sliderTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example3/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example3
{
    static class Program
    {
        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 3", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create some centered text
            OpenGL.UI.Text selectText = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._16pt, "Pick A Color:", OpenGL.UI.BMFont.Justification.Center);
            selectText.Position = new Point(0, 80);
            selectText.RelativeTo = OpenGL.UI.Corner.Center;

            // add the two text object to the UI
            OpenGL.UI.UserInterface.AddElement(selectText);

            // create the color picker itself
            OpenGL.UI.ColorGradient gradient = new OpenGL.UI.ColorGradient();
            gradient.RelativeTo = OpenGL.UI.Corner.Center;
            gradient.Position = new Point(-20, 0);
            gradient.OnColorChange = (sender, e) => selectText.Color = gradient.Color;

            // and create a hue slider that can control the types of colors shown in the color picker
            OpenGL.UI.HueGradient hue = new OpenGL.UI.HueGradient();
            hue.RelativeTo = OpenGL.UI.Corner.Center;
            hue.Position = new Point(80, 0);

            // add the color picker and its hue slider to the UI
            OpenGL.UI.UserInterface.AddElement(gradient);
            OpenGL.UI.UserInterface.AddElement(hue);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example9/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example9
{
    static class Program
    {
        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 9", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            OpenGL.UI.Text text = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._16pt, "Type Something:");
            text.RelativeTo = OpenGL.UI.Corner.Center;
            text.Position = new Point(-260, -10);

            // create a text input control
            OpenGL.UI.TextInput textInput = new OpenGL.UI.TextInput(OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"));
            textInput.Size = new Point(300, 20);
            textInput.Position = new Point(50, 0);
            textInput.RelativeTo = OpenGL.UI.Corner.Center;
            textInput.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 1.0f);

            // add the text input control to the user interface
            OpenGL.UI.UserInterface.AddElement(textInput);
            OpenGL.UI.UserInterface.AddElement(text);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>gui4opengl/Controls/ColorPicker.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class ColorGradient : UIElement
    {
        #region Variables
        private VAO gradientQuad;
        private float selx = 0.0f, sely = 1.0f, h = 1.0f;
        private bool mouseDown = false;

        public float Hue
        {
            get { return h; }
            set
            {
                h = value;
                Program.Use();
                Program["hue"].SetValue(new HSLColor(value, 1, 0.5f).ToVector());
                UpdateColor();
            }
        }

        private Vector3 color;

        public Vector3 Color
        {
            get { return color; }
            set
            {

            }
        }

        public OnMouse OnColorChange { get; set; }
        #endregion

        #region Constructor
        public ColorGradient()
        {
            var colorGradient = UserInterface.GetElement("ColorGradient");
            if (colorGradient != null) throw new Exception("Only one color picker can currently exist at once.  This is a limitation I intend to remove soon.");

            this.Program = Shaders.GradientShader;

            this.Program.Use();
            this.Program["hue"].SetValue(new Vector3(h, 0, 0));
            this.Program["sel"].SetValue(new Vector2(selx, sely));
            this.gradientQuad = Geometry.CreateQuad(this.Program, Vector2.Zero, new Vector2(150, 150));

            this.RelativeTo = Corner.TopLeft;
            this.Position = new Point(30, 50);
            this.Size = new Point(150, 150);
            this.Name = "ColorGradient";

            // set up the events for the mouse to move the indicator around
            this.OnMouseDown = new OnMouse((sender, eventArgs) =>
            {
                mouseDown = (eventArgs.Button == MouseButton.Left);
                UpdateMousePosition(eventArgs.Location.X, eventArgs.Location.Y);
            });
            this.OnMouseUp = new OnMouse((sender, eventArgs) => mouseDown = (eventArgs.Button == MouseButton.Left ? false : mouseDown));
            this.OnMouseLeave = new OnMouse((sender, eventArgs) => mouseDown = false);
            this.OnMouseMove = new OnMouse((sender, eventArgs) => UpdateMousePosition(eventArgs.Location.X, eventArgs.Location.Y));

            UpdateColor();
        }
        #endregion

        #region Methods
        private void UpdateMousePosition(int x, int y)
        {
            if (!mouseDown) return;

            selx = Math.Min(1, (float)(x - CorrectedPosition.X) / Size.X);
            sely = Math.Min(1, (float)((UserInterface.Height - y) - CorrectedPosition.Y) / Size.Y);

            Program.Use();
            Program["sel"].SetValue(new Vector2(selx, sely));

            UpdateColor();
        }

        private void UpdateColor()
        {
            // create our HSL color
            Vector3 color = new HSLColor(h, 1, 0.5f).ToVector();

            // now blend the white and color together
            Vector3 blend1 = color * selx + Vector3.One * (float)(1 - selx);

            // finally blend the black and blend1 together
            this.color = blend1 * sely;

            if (OnColorChange != null) OnColorChange(this, new MouseEventArgs());
        }
        #endregion

        #region UIElement Methods
        public override void Draw()
        {
            Program.Use();
            gradientQuad.Draw();
        }

        public override void OnResize()
        {
            base.OnResize();

            Program.Use();
            Program["model_matrix"].SetValue(Matrix4.CreateTranslation(new Vector3(CorrectedPosition.X, CorrectedPosition.Y, 0)));
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            gradientQuad.DisposeChildren = true;
            gradientQuad.Dispose();
        }
        #endregion
    }

    public class HueGradient : UIElement
    {
        #region Variables
        private VAO hueQuad;
        private bool mouseDown = false;
        #endregion

        #region Constructor
        public HueGradient()
        {
            this.Program = Shaders.HueShader;

            this.Program.Use();
            this.Program["hue"].SetValue(0f);
            this.hueQuad = Geometry.CreateQuad(this.Program, Vector2.Zero, new Vector2(26, 150));

            this.RelativeTo = Corner.TopLeft;
            this.Position = new Point(185, 50);
            this.Size = new Point(26, 150);
            this.Name = "HueGradient";

            // set up the events for the mouse to move the indicator around
            this.OnMouseDown = new OnMouse((sender, eventArgs) =>
            {
                mouseDown = (eventArgs.Button == MouseButton.Left);
                UpdateMousePosition(eventArgs.Location.X, eventArgs.Location.Y);
            });
            this.OnMouseUp = new OnMouse((sender, eventArgs) => mouseDown = (eventArgs.Button == MouseButton.Left ? false : mouseDown));
            this.OnMouseLeave = new OnMouse((sender, eventArgs) => mouseDown = false);
            this.OnMouseMove = new OnMouse((sender, eventArgs) => UpdateMousePosition(eventArgs.Location.X, eventArgs.Location.Y));
        }
        #endregion

        #region Methods
        private void UpdateMousePosition(int x, int y)
        {
            if (!mouseDown) return;

            // calculate the selected hue based on the mouse position
            float hue = ((UserInterface.Height - y) - CorrectedPosition.Y) / (float)Size.Y;
            Program.Use();
            Program["hue"].SetValue((float)((UserInterface.Height - y) - CorrectedPosition.Y));

            // asks the user interface for the applicable color gradient
            // this will need to be modified if multiple color gradients are on the screen at once
            // which I can't imagine happening currently, but who knows
            var colorGradient = UserInterface.GetElement("ColorGradient");
            if (colorGradient != null) ((ColorGradient)colorGradient).Hue = hue;
        }
        #endregion

        #region UIElement Methods
        public override void Draw()
        {
            Gl.Enable(EnableCap.Blend);

            Program.Use();
            hueQuad.Draw();

            Gl.Disable(EnableCap.Blend);
        }

        public override void OnResize()
        {
            base.OnResize();

            Program.Use();
            Program["model_matrix"].SetValue(Matrix4.CreateTranslation(new Vector3(CorrectedPosition.X, CorrectedPosition.Y, 0)));
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            hueQuad.DisposeChildren = true;
            hueQuad.Dispose();
        }
        #endregion
    }

    public class HSLColor
    {
        #region Properties
        public float H { get; private set; }

        public float S { get; private set; }

        public float L { get; private set; }
        #endregion

        #region Constructors
        public HSLColor(float h, float s, float l)
        {
            this.H = h;
            this.S = s;
            this.L = l;
        }

        public HSLColor(Vector3 c)
        {
            float r = c.X;
            float g = c.Y;
            float b = c.Z;

            float _Min = Math.Min(Math.Min(r, g), b);
            float _Max = Math.Max(Math.Max(r, g), b);
            float _Delta = _Max - _Min;

            H = 0;
            S = 0;
            L = (float)((_Max + _Min) / 2.0f);

            if (_Delta != 0)
            {
                if (L < 0.5f)
                {
                    S = (float)(_Delta / (_Max + _Min));
                }
                else
                {
                    S = (float)(_Delta / (2.0f - _Max - _Min));
                }


                if (r == _Max)
                {
                    H = (g - b) / _Delta;
                }
                else if (g == _Max)
                {
                    H = 2f + (b - r) / _Delta;
                }
                else if (b == _Max)
                {
                    H = 4f + (r - g) / _Delta;
                }
            }

            H = H * 60f;
            if (H < 0) H += 360;
            H /= 360f;
        }

        public HSLColor(System.Drawing.Color c)
            : this(c.R / 255f, c.G / 255f, c.B / 255f)
        {
        }
        #endregion

        #region Methods
        public Vector3 ToVector()
        {
            float r, g, b;

            if (S == 0) r = g = b = L;
            else
            {
                float q = (L < 0.5f ? L * (1 + S) : L + S - L * S);
                float p = 2 * L - q;
                r = HUE2RGB(p, q, H + 1 / 3.0f);
                g = HUE2RGB(p, q, H);
                b = HUE2RGB(p, q, H - 1 / 3.0f);
            }

            return new Vector3(r, g, b);
        }

        private static float HUE2RGB(float p, float q, float t)
        {
            if (t < 0) t += 1;
            if (t > 1) t -= 1;
            if (t < 1 / 6.0) return p + (q - p) * 6 * t;
            if (t < 1 / 2.0) return q;
            if (t < 2 / 3.0) return p + (q - p) * (2 / 3.0f - t) * 6;
            return p;
        }
        #endregion
    }
}


<|start_filename|>Examples/Example1/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example1
{
    static class Program
    {
        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 1", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create some centered text
            OpenGL.UI.Text welcome = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._24pt, "Welcome to OpenGL", OpenGL.UI.BMFont.Justification.Center);
            welcome.RelativeTo = OpenGL.UI.Corner.Center;

            // create some colored text
            OpenGL.UI.Text coloredText = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._24pt, "using C#", OpenGL.UI.BMFont.Justification.Center);
            coloredText.Position = new Point(0, -30);
            coloredText.Color = new Vector3(0.2f, 0.3f, 1f);
            coloredText.RelativeTo = OpenGL.UI.Corner.Center;

            // add the two text object to the UI
            OpenGL.UI.UserInterface.AddElement(welcome);
            OpenGL.UI.UserInterface.AddElement(coloredText);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }

        private static void OnMouseClick(int button, int state, int x, int y)
        {
            // take care of mapping the Glut buttons to the UI enums
            if (!OpenGL.UI.UserInterface.OnMouseClick(button + 1, (state == 0 ? 1 : 0), x, y))
            {
                // do other picking code here if necessary
            }
        }

        private static void OnMouseMove(int x, int y)
        {
            if (!OpenGL.UI.UserInterface.OnMouseMove(x, y))
            {
                // do other picking code here if necessary
            }
        }
    }
}


<|start_filename|>gui4opengl/Controls/TextInput.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class TextInput : UIContainer
    {
        #region Variables
        private Text text;
        private bool hasFocus = false;
        #endregion

        #region Properties
        /// <summary>
        /// CarriageReturn callback delegate prototype.
        /// </summary>
        /// <param name="entry">The TextEntry that received the carriage return signal.</param>
        /// <param name="text">The text contained in the TextEntry when the carriage return signal was received.</param>
        public delegate void OnTextEvent(TextInput entry, string text);

        /// <summary>
        /// Event is called when the carriage return button (Enter on most keyboards) is pressed.
        /// </summary>
        public OnTextEvent OnCarriageReturn { get; set; }

        /// <summary>
        /// Event is called when any text is entered or deleted.
        /// </summary>
        public OnTextEvent OnTextEntry { get; set; }

        /// <summary>
        /// The contents of the TextEntry.
        /// </summary>
        public string String
        {
            get { return text.String; }
        }
        #endregion

        #region Constructor
        public TextInput(BMFont font, string s = "")
            : base(new Point(0, 0), new Point(200, font.Height), "TextEntry" + UserInterface.GetUniqueElementID())
        {
            text = new Text(Shaders.FontShader, font, s, BMFont.Justification.Left);
            text.RelativeTo = Corner.Fill;
            text.Padding = new Point(5, 0);

            this.OnMouseClick = new OnMouse((o, e) => text.OnMouseClick(o, e));

            text.OnMouseClick = new OnMouse((o, e) =>
                {
                    if (hasFocus) return;
                    hasFocus = true;

                    // take control of the key bindings
                    Input.PushKeyBindings();

                    Input.SubscribeAll(new Event((key, state) =>
                        {
                            // give 16 pixels of padding on the right
                            if (!state || text.TextSize.X > Size.X - 16) return;

                            text.String += key;

                            if (OnTextEntry != null) OnTextEntry(this, String);
                        }));

                    // delete key
                    Input.Subscribe((char)8, new Event(() =>
                        {
                            if (text.String.Length == 0) return;
                            else text.String = text.String.Substring(0, text.String.Length - 1);

                            if (OnTextEntry != null) OnTextEntry(this, String);
                        }));

                    // carriage return
                    Input.Subscribe((char)13, new Event(() =>
                        {
                            if (OnCarriageReturn != null) OnCarriageReturn(this, String);
                        }));

                    // escape key
                    Input.Subscribe((char)27, new Event(() => text.OnLoseFocus(null, null)));

                    // restore the key bindings when we lose focus
                    text.OnLoseFocus = new OnFocus((sender, newFocus) =>
                        {
                            if (!hasFocus) return;
                            hasFocus = false;

                            Input.PopKeyBindings();
                        }); 
                });

            this.AddElement(text);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (hasFocus)
            {
                hasFocus = false;

                //Input.PopKeyBindings();
            }
        }

        public void Clear()
        {
            text.String = String.Empty;
        }
        #endregion
    }
}


<|start_filename|>gui4opengl/Controls/CheckBox.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class CheckBox : UIContainer
    {
        #region Get/Set Font and Text
        private Text text;
        private BMFont font;
        private string textString;

        /// <summary>
        /// The font to use when rendering the descriptive text for this checkbox.
        /// Will rebuild the string VAO when modified.
        /// </summary>
        public BMFont Font
        {
            get { return font; }
            set
            {
                if (text != null) text.Dispose();
                font = value;
                if (textString != null && textString.Length != 0) this.Text = textString;
            }
        }

        /// <summary>
        /// The descriptive text to use for this checkbox (placed to the right of the checkbox).
        /// Will rebuild the string VAO when modified.
        /// </summary>
        public string Text
        {
            get { return textString; }
            set
            {
                textString = value;
                if (text == null)
                {
                    if (font != null)
                    {
                        text = new Text(Shaders.FontShader, font, textString, BMFont.Justification.Left);
                        text.Size = new Point(0, this.Size.Y);
                        text.RelativeTo = Corner.BottomLeft;
                        text.Position = new Point(UncheckedTexture.Size.Width + 6, Size.Y / 2 - text.TextSize.Y / 2);

                        this.AddElement(text);
                    }
                }
                else text.String = textString;
            }
        }

        /// <summary>
        /// An event that is fired when the checkbox changes state.
        /// </summary>
        public OnMouse OnCheckedChanged { get; set; }
        #endregion

        #region Checkbox Textures and State
        private Button checkBox;
        private bool isChecked;

        /// <summary>
        /// Texture to use when the checkbox is unchecked.
        /// Should be the same size as CheckedTexture as well as the CheckBox.Size property.
        /// </summary>
        public Texture UncheckedTexture { get; set; }

        /// <summary>
        /// Texture to use when the checkbox is checked.
        /// Should be the same size as UncheckedTexture as well as the CheckBox.Size property.
        /// </summary>
        public Texture CheckedTexture { get; set; }

        /// <summary>
        /// True if the checkbox is currently checked.
        /// False if the checkbox is unchecked.
        /// </summary>
        public bool Checked
        {
            get { return isChecked; }
            set
            {
                isChecked = value;
                if (OnCheckedChanged != null) OnCheckedChanged(this, new MouseEventArgs());

                if (isChecked) checkBox.BackgroundTexture = CheckedTexture;
                else checkBox.BackgroundTexture = UncheckedTexture;
            }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Creates a simple checkbox user interface element which can be used
        /// for setting/modifying the state of a boolean value.
        /// This can be useful in preferences as well as other places in the user interface.
        /// </summary>
        /// <param name="uncheckedTexture">A texture to use when the checkbox is unchecked.  Should be the same size as checkedTexture.</param>
        /// <param name="checkedTexture">A texture to use when the checkbox is checked.  Should be the same size as uncheckedTexture.</param>
        /// <param name="font">A BMFont to use when rendering the descriptive text of this checkbox.</param>
        /// <param name="text">The descriptive text to render to the right of this checkbox.</param>
        public CheckBox(Texture uncheckedTexture, Texture checkedTexture, BMFont font, string text)
            : base(new Point(0, 0), new Point(uncheckedTexture.Size.Width, uncheckedTexture.Size.Height), "CheckBox" + UserInterface.GetUniqueElementID())
        {
            this.UncheckedTexture = uncheckedTexture;
            this.CheckedTexture = checkedTexture;

            checkBox = new Button(UncheckedTexture);
            checkBox.BackgroundColor = new Vector4(0, 0, 0, 0);
            checkBox.RelativeTo = Corner.BottomLeft;
            checkBox.Size = new Point(uncheckedTexture.Size.Width, uncheckedTexture.Size.Height);
            this.AddElement(checkBox);

            this.Font = font;
            this.Text = text;

            checkBox.OnMouseClick = new OnMouse((o, e) => this.Checked = !this.Checked);
        }
        #endregion
    }
}


<|start_filename|>gui4opengl/Controls/Button.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class Button : UIElement
    {
        #region Properties
        public bool Enabled { get; set; }

        public Vector4 EnabledColor { get; set; }
        #endregion
        
        #region Text Support
        private Text text;
        private BMFont font;
        private string textString;

        public BMFont Font
        {
            get { return font; }
            set
            {
                if (text != null) text.Dispose();
                font = value;
                if (textString != null && textString.Length != 0) text = new Text(Shaders.FontShader, font, textString, BMFont.Justification.Center);
            }
        }

        public string Text
        {
            get { return textString; }
            set
            {
                textString = value;
                if (text == null)
                {
                    if (font != null)
                    {
                        text = new Text(Shaders.FontShader, font, textString, BMFont.Justification.Center);
                        text.Size = this.Size;
                    }
                }
                else text.String = textString;
            }
        }
        #endregion

        #region Constructors
        public Button(Texture texture)
        {
            this.BackgroundColor = Vector4.Zero;
            this.EnabledColor = Vector4.Zero;
            this.BackgroundTexture = texture;

            this.RelativeTo = Corner.TopLeft;
            this.Size = new Point(texture.Size.Width, texture.Size.Height);
        }

        public Button(int width, int height)
        {
            this.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 1f);
            this.EnabledColor = new Vector4(0.3f, 0.9f, 0.3f, 1f);

            this.RelativeTo = Corner.TopLeft;
            this.Size = new Point(width, height);
        }
        #endregion

        #region UIElement Overrides (OnResize, Dispose, Draw)
        public override void OnResize()
        {
            if (text != null) text.Size = this.Size;

            base.OnResize();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (text != null) text.Dispose();
        }

        public override void Draw()
        {
            base.DrawQuadColored(Enabled ? EnabledColor : BackgroundColor);
            if (BackgroundTexture != null) base.DrawQuadTextured();

            if (text != null)
            {
                text.CorrectedPosition = this.CorrectedPosition;
                text.Draw();
            }
        }
        #endregion
    }
}


<|start_filename|>Examples/Example2/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example2
{
    static class Program
    {
        private static Texture[] textures;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 2", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create some centered text
            OpenGL.UI.Text selectText = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._24pt, "Select A Character", OpenGL.UI.BMFont.Justification.Center);
            selectText.Position = new Point(0, 50);
            selectText.RelativeTo = OpenGL.UI.Corner.Center;

            OpenGL.UI.Text characterName = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._16pt, "", OpenGL.UI.BMFont.Justification.Center);
            characterName.RelativeTo = OpenGL.UI.Corner.Center;
            characterName.Position = new Point(0, -70);

            // add the two text object to the UI
            OpenGL.UI.UserInterface.AddElement(selectText);
            OpenGL.UI.UserInterface.AddElement(characterName);

            // the license for these icons is located in the data folder
            string[] characters = new string[] { "boy.png", "man.png", "girl1.png", "girl2.png", "girl3.png" };
            textures = new Texture[characters.Length];
            int xoffset = -characters.Length * 80 / 2 + 40;

            for (int i = 0; i < characters.Length; i++)
            {
                string character = characters[i];

                // load a texture that will be used by a button
                textures[i] = new Texture(string.Format("data/{0}", character));

                // create buttons in a row, each of which uses a Texture (the Texture gives the initial size of the Button in pixels)
                OpenGL.UI.Button button = new OpenGL.UI.Button(textures[i]);
                button.Position = new Point(xoffset, 5);
                button.RelativeTo = OpenGL.UI.Corner.Center;

                // change the color of the button when entering/leaving/clicking with the mouse
                button.OnMouseEnter = (sender, e) => button.BackgroundColor = new Vector4(0, 1f, 0.2f, 1.0f);
                button.OnMouseLeave = (sender, e) => button.BackgroundColor = Vector4.Zero;
                button.OnMouseDown = (sender, e) => button.BackgroundColor = new Vector4(0, 0.6f, 1f, 1f);
                button.OnMouseUp = (sender, e) => button.BackgroundColor = (OpenGL.UI.UserInterface.Selection == button ? new Vector4(0, 1f, 0.2f, 1.0f) : Vector4.Zero);

                // update the text with the character name when the button is clicked
                button.OnMouseClick = (sender, e) => characterName.String = string.Format("You selected {0}!", character);

                OpenGL.UI.UserInterface.AddElement(button);

                xoffset += 80;
            }

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            if (textures != null) foreach (var texture in textures) texture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }

        private static void OnMouseClick(int button, int state, int x, int y)
        {
            // take care of mapping the Glut buttons to the UI enums
            if (!OpenGL.UI.UserInterface.OnMouseClick(button + 1, (state == 0 ? 1 : 0), x, y))
            {
                // do other picking code here if necessary
            }
        }

        private static void OnMouseMove(int x, int y)
        {
            if (!OpenGL.UI.UserInterface.OnMouseMove(x, y))
            {
                // do other picking code here if necessary
            }
        }
    }
}


<|start_filename|>gui4opengl/Controls/Text.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace OpenGL.UI
{
    public class Text : UIElement
    {
        #region Built-In Font Sizes
        public enum FontSize
        {
            _12pt = 0,
            _14pt = 1,
            _16pt = 2,
            _24pt = 3,
            _32pt = 4,
            _48pt = 5
        }

        public static BMFont FontFromSize(FontSize font)
        {
            switch (font)
            {
                case FontSize._12pt: return BMFont.LoadFont("fonts/font12.fnt");
                case FontSize._14pt: return BMFont.LoadFont("fonts/font14.fnt");
                case FontSize._16pt: return BMFont.LoadFont("fonts/font16.fnt");
                case FontSize._24pt: return BMFont.LoadFont("fonts/font24.fnt");
                case FontSize._32pt: return BMFont.LoadFont("fonts/font32.fnt");
                case FontSize._48pt: return BMFont.LoadFont("fonts/font48.fnt");
                default: //Logger.Instance.WriteLine("Unknown font " + font + " requested.");
                    return BMFont.LoadFont("fonts/font12.fnt");
            }
        }
        #endregion

        #region Private Fields
        private string text;
        private BMFont bitmapFont;
        private Vector3 color;
        private BMFont.Justification justification;
        #endregion

        #region Public Properties
        public Vector3 Color
        {
            get { return color; }
            set { color = value; }
        }

        public BMFont.Justification Justification
        {
            get { return justification; }
            set
            {
                if (justification != value)
                {
                    justification = value;
                    bitmapFont.CreateString(VAO, text, color, justification);
                }
            }
        }

        private VAO<Vector3, Vector2> VAO;

        public Point Padding { get; set; }

        public Point TextSize { get; private set; }

        public string String
        {
            get { return text; }
            set
            {
                // do not cause the text to update if it is the same
                if (text == value || value == null) return;

                if (text != null && text.Length == value.Length)
                {
                    bitmapFont.CreateString(VAO, value, Color, Justification);
                }
                else
                {
                    if (this.VAO != null) this.VAO.Dispose();
                    this.VAO = bitmapFont.CreateString(Program, value, Color, Justification);
                    this.VAO.DisposeChildren = true;
                }

                text = value;
                this.TextSize = new Point(bitmapFont.GetWidth(text), bitmapFont.Height);
            }
        }
        #endregion

        #region Constructors
        public Text(ShaderProgram program, BMFont font, string text, BMFont.Justification justification = BMFont.Justification.Left)
            : this(program, font, text, new Vector3(1, 1, 1), justification)
        {
        }

        public Text(FontSize font, string text, BMFont.Justification justification = BMFont.Justification.Left)
            : this(Shaders.FontShader, FontFromSize(font), text, Vector3.One, justification)
        {
        }

        public Text(FontSize font, string text, Vector3 color, BMFont.Justification justification = BMFont.Justification.Left)
            : this(Shaders.FontShader, FontFromSize(font), text, color, justification)
        {
        }

        public Text(ShaderProgram program, BMFont font, string text, Vector3 color, BMFont.Justification justification = BMFont.Justification.Left)
        {
            this.bitmapFont = font;
            this.Program = program;
            this.Justification = justification;
            this.Color = color;
            this.String = text;
            this.Position = new Point(0, 0);
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Updates the current VAO with a new font.
        /// Will use the current 'String' if it exists, otherwise will leave VAO as null.
        /// </summary>
        /// <param name="font">The new font size to use with this Text.</param>
        public void UpdateFontSize(FontSize font)
        {
            this.bitmapFont = FontFromSize(font);

            if (string.IsNullOrEmpty(this.String)) return;

            if (this.VAO != null) bitmapFont.CreateString(VAO, this.String, Color, Justification);
            else
            {
                this.VAO = bitmapFont.CreateString(Program, this.String, Color, Justification);
                this.VAO.DisposeChildren = true;
            }

            this.TextSize = new Point(bitmapFont.GetWidth(text), bitmapFont.Height);
        }

        public void DrawWithCharacterCount(int count)
        {
            int vertexCount = Math.Min(count * 6, VAO.VertexCount);

            Gl.ActiveTexture(TextureUnit.Texture0);
            Gl.BindTexture(bitmapFont.FontTexture);

            Gl.Enable(EnableCap.Blend);
            Program.Use();
            Program["position"].SetValue(new Vector2(CorrectedPosition.X + Padding.X, CorrectedPosition.Y + Padding.Y));
            Program["color"].SetValue(color);
            VAO.BindAttributes(Program);
            Gl.DrawElements(BeginMode.Triangles, vertexCount, DrawElementsType.UnsignedInt, IntPtr.Zero);
            Gl.Disable(EnableCap.Blend);
        }
        #endregion

        #region UIElement Overrides (Draw, Pick, Dispose)
        public override void Draw()
        {
            base.Draw();

            Gl.ActiveTexture(TextureUnit.Texture0);
            Gl.BindTexture(bitmapFont.FontTexture);

            int yoffset = 0;
            if (this.Size.Y > TextSize.Y)
                yoffset = (Size.Y - TextSize.Y) / 2;

            Gl.Enable(EnableCap.Blend);
            Program.Use();
            if (this.Justification == BMFont.Justification.Center) Program["position"].SetValue(new Vector2(CorrectedPosition.X + Padding.X + Size.X / 2, CorrectedPosition.Y + Padding.Y + yoffset));
            else Program["position"].SetValue(new Vector2(CorrectedPosition.X + Padding.X, CorrectedPosition.Y + Padding.Y + yoffset));
            Program["color"].SetValue(color);
            VAO.Draw();
            Gl.Disable(EnableCap.Blend);
        }

        protected override void Dispose(bool disposing)
        {
            if (VAO != null)
            {
                VAO.Dispose();
                VAO = null;
            }

            base.Dispose(true);
        }
        #endregion
    }
}


<|start_filename|>Examples/Example6/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example6
{
    static class Program
    {
        private static Texture checkBoxTexture, checkBoxCheckedTexture;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 6", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create a checkbox with a specified texture
            checkBoxTexture = new Texture("data/checkBox.png");
            checkBoxCheckedTexture = new Texture("data/checkBoxChecked.png");

            OpenGL.UI.CheckBox checkbox1 = new OpenGL.UI.CheckBox(checkBoxTexture, checkBoxCheckedTexture, OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"), "Check Me!");
            checkbox1.RelativeTo = OpenGL.UI.Corner.Center;
            checkbox1.Position = new Point(-50, 12);
            checkbox1.OnCheckedChanged = (sender, e) => checkbox1.Text = (checkbox1.Checked ? "Thanks!" : "Check Me!");

            OpenGL.UI.CheckBox checkbox2 = new OpenGL.UI.CheckBox(checkBoxTexture, checkBoxCheckedTexture, OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"), "Check Me Too!");
            checkbox2.RelativeTo = OpenGL.UI.Corner.Center;
            checkbox2.Position = new Point(-50, -12);
            checkbox2.OnCheckedChanged = (sender, e) => checkbox2.Text = (checkbox2.Checked ? "Thanks!" : "Check Me Too!");

            // add both checkbox controls to the user interface
            OpenGL.UI.UserInterface.AddElement(checkbox1);
            OpenGL.UI.UserInterface.AddElement(checkbox2);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            checkBoxTexture.Dispose();
            checkBoxCheckedTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example8/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example8
{
    static class Program
    {
        private static Texture scrollTexture;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 8", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // load a texture that we'll use for the scroll bar of the textbox
            scrollTexture = new Texture("data/scrollBar.png");

            // create a textbox
            OpenGL.UI.ListBox listBox = new OpenGL.UI.ListBox(scrollTexture, scrollTexture, OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"), new string[] { "Item 1", "Item 2", "Item 3" });
            listBox.RelativeTo = OpenGL.UI.Corner.Center;
            listBox.Size = new Point(200, 20);
            listBox.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 1.0f);
            listBox.Invalidate();
            
            // add the list box to the user interface
            OpenGL.UI.UserInterface.AddElement(listBox);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            scrollTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example10/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example10
{
    static class Program
    {
        private static Texture scrollTexture;
        private static OpenGL.UI.Button divider;
        private static OpenGL.UI.UIContainer leftContainer, rightContainer;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 10", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create the left and right containers
            leftContainer = new OpenGL.UI.UIContainer(new Point(Window.Width / 2, Window.Height), "LeftContainer");
            rightContainer = new OpenGL.UI.UIContainer(new Point(Window.Width / 2, Window.Height), "RightContainer");

            leftContainer.RelativeTo = OpenGL.UI.Corner.BottomLeft;
            rightContainer.RelativeTo = OpenGL.UI.Corner.BottomRight;

            // add the containers to the user interface
            OpenGL.UI.UserInterface.AddElement(leftContainer);
            OpenGL.UI.UserInterface.AddElement(rightContainer);

            // add some cool stuff to the containers
            scrollTexture = new Texture("data/scrollTexture.png");

            // create a textbox with word wrapping for the left container
            OpenGL.UI.TextBox textBox = new OpenGL.UI.TextBox(OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"), scrollTexture);
            textBox.Write("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis eget vehicula orci. Nulla nibh nulla, suscipit non neque sed, placerat efficitur velit. Sed convallis gravida tincidunt. Praesent vehicula nibh leo, at consequat nisi condimentum ullamcorper. Vivamus pulvinar accumsan maximus. Integer luctus elit porttitor nisi sollicitudin, eget porttitor odio tincidunt. Sed elit justo, suscipit non dui ut, eleifend euismod nibh. Nullam ac fermentum nisl. In convallis id leo sit amet eleifend. Suspendisse eu ligula pulvinar ex facilisis cursus ac ac velit. In ut turpis nec neque vehicula eleifend. Morbi in tempus est. Vivamus nisi nunc, pharetra quis scelerisque ut, tempor id dui.");
            textBox.RelativeTo = OpenGL.UI.Corner.Fill;
            textBox.Padding = new Point(6, 0);
            leftContainer.AddElement(textBox);
            textBox.OnResize();

            // build 10 buttons for the right container
            for (int i = 0; i < 10; i++)
            {
                OpenGL.UI.Button button = new OpenGL.UI.Button(200, 30);
                button.Font = OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt");
                button.Text = string.Format("Button {0}", i);
                button.RelativeTo = OpenGL.UI.Corner.Center;
                button.Position = new Point(0, 200 - i * 40);
                rightContainer.AddElement(button);
                button.OnResize();

                button.OnMouseEnter = (sender, e) => button.BackgroundColor = new Vector4(0.5f, 0.5f, 1.0f, 1.0f);
                button.OnMouseLeave = (sender, e) => button.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 1.0f);
            }

            // add a control to resize the left/right containers
            divider = new OpenGL.UI.Button(8, Window.Height);
            divider.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 0.5f);
            divider.RelativeTo = OpenGL.UI.Corner.BottomLeft;
            divider.Position = new Point(Window.Width / 2 - divider.Size.X / 2, 0);

            bool onMouseDown = false;

            // handle mouse events on the divider
            divider.OnMouseDown = (sender, e) => onMouseDown = true;
            divider.OnMouseUp = (sender, e) => onMouseDown = false;
            divider.OnMouseMove = (sender, e) =>
            {
                if (onMouseDown) ResizeControls(e.Location.X - e.LastLocaton.X);
            };

            // make sure to layout the controls if the window is resized
            Window.OnReshapeCallbacks.Add(() => ResizeControls(0));

            // add the divider to the user interface
            OpenGL.UI.UserInterface.AddElement(divider);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void ResizeControls(int dx)
        {
            int x = divider.Position.X + dx;// (e.Location.X - e.LastLocaton.X);
            x = Math.Min(Window.Width - 110, x);

            // set the position of the divider
            divider.Position = new Point(x, divider.Position.Y);

            // update the container sizes
            x += divider.Size.X / 2;
            leftContainer.Size = new Point(x, Window.Height);
            rightContainer.Size = new Point(Window.Width - x, Window.Height);

            // resize the buttons to make them fit in the right container
            foreach (var button in rightContainer.Elements)
                button.Size = new Point(Math.Min(200, rightContainer.Size.X - 16), 30);

            OpenGL.UI.UserInterface.UIWindow.OnResize();
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            scrollTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example4/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example4
{
    static class Program
    {
        private static Texture menuTexture, menuSelectedTexture;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 4", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // create a container that will store all of our color picker content
            OpenGL.UI.UIContainer colorPickerContainer = new OpenGL.UI.UIContainer();
            colorPickerContainer.Size = new Point(240, 190);
            colorPickerContainer.Position = new Point(20, 20);
            colorPickerContainer.RelativeTo = OpenGL.UI.Corner.TopLeft;

            // create a menu bar that will have two different textures
            menuTexture = new Texture("data/menu.png");
            menuSelectedTexture = new Texture("data/menuSelected.png");

            OpenGL.UI.Button menu = new OpenGL.UI.Button(menuTexture);
            colorPickerContainer.AddElement(menu);

            // place some text within the menu bar
            OpenGL.UI.Text menuText = new OpenGL.UI.Text(OpenGL.UI.Text.FontSize._12pt, "Color Picker");
            menuText.RelativeTo = OpenGL.UI.Corner.TopLeft;
            menuText.Position = new Point(4, 17);
            colorPickerContainer.AddElement(menuText);

            // add some events that will move the entire color picker container with the menu bar
            bool moving = false;
            menu.OnMouseDown = (sender, e) =>
                {
                    moving = true;
                    menu.BackgroundTexture = menuSelectedTexture;   // make it look nice by swapping the menubar texture
                };
            menu.OnMouseUp = (sender, e) =>
                {
                    moving = false;
                    menu.BackgroundTexture = menuTexture;   // make sure to restore the menubar texture
                };
            menu.OnMouseMove = (sender, e) =>
                {
                    if (moving)
                    {
                        int x = colorPickerContainer.Position.X + OpenGL.UI.UserInterface.MousePosition.X - OpenGL.UI.UserInterface.LastMousePosition.X;
                        int y = colorPickerContainer.Position.Y + OpenGL.UI.UserInterface.MousePosition.Y - OpenGL.UI.UserInterface.LastMousePosition.Y;
                        colorPickerContainer.Position = new Point(x, y);
                        colorPickerContainer.OnResize();
                    }
                };

            // create the color picker itself
            OpenGL.UI.ColorGradient gradient = new OpenGL.UI.ColorGradient();
            gradient.Position = new Point(30, 30);

            // and create a hue slider that can control the types of colors shown in the color picker
            OpenGL.UI.HueGradient hue = new OpenGL.UI.HueGradient();
            hue.Position = new Point(190, 30);

            // add the color picker and its hue slider to the UI
            colorPickerContainer.AddElement(gradient);
            colorPickerContainer.AddElement(hue);

            // add the entire container to the user interface
            OpenGL.UI.UserInterface.AddElement(colorPickerContainer);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            menuTexture.Dispose();
            menuSelectedTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}


<|start_filename|>Examples/Example7/Program.cs<|end_filename|>
﻿using System;

using OpenGL;
using OpenGL.Platform;

namespace Example7
{
    static class Program
    {
        private static Texture scrollTexture;

        static void Main()
        {
            Window.CreateWindow("OpenGL UI: Example 7", 1280, 720);

            // add a reshape callback to update the UI
            Window.OnReshapeCallbacks.Add(() => OpenGL.UI.UserInterface.OnResize(Window.Width, Window.Height));

            // add a close callback to make sure we dispose of everything properly
            Window.OnCloseCallbacks.Add(OnClose);

            // enable depth testing to ensure correct z-ordering of our fragments
            Gl.Enable(EnableCap.DepthTest);
            Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // initialize the user interface
            OpenGL.UI.UserInterface.InitUI(Window.Width, Window.Height);

            // load a texture that we'll use for the scroll bar of the textbox
            scrollTexture = new Texture("data/scrollBar.png");

            // create a textbox
            OpenGL.UI.TextBox textBox = new OpenGL.UI.TextBox(OpenGL.UI.BMFont.LoadFont("fonts/font16.fnt"), scrollTexture);
            textBox.RelativeTo = OpenGL.UI.Corner.Center;
            textBox.Size = new Point(400, 200);
            textBox.BackgroundColor = new Vector4(0.3f, 0.3f, 0.3f, 1.0f);

            // put a bunch of text into the textbox
            textBox.WriteLine("Hello!");
            textBox.WriteLine("This is a textbox, and it supports automatic word wrapping!");
            textBox.WriteLine(new Vector3(0.5f, 0.7f, 1.0f), "It also supports colors!");
            textBox.Write("It even supports ");
            textBox.Write(new Vector3(1, 0, 0), "multiple ");
            textBox.Write(new Vector3(0, 1, 0), "colors ");
            textBox.Write(new Vector3(0, 0, 1), "on ");
            textBox.WriteLine("the same line!");
            textBox.WriteLine("It also supports a scroll bar and the ability to scroll through lots of text!");
            textBox.WriteLine("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis eget vehicula orci. Nulla nibh nulla, suscipit non neque sed, placerat efficitur velit. Sed convallis gravida tincidunt. Praesent vehicula nibh leo, at consequat nisi condimentum ullamcorper. Vivamus pulvinar accumsan maximus. Integer luctus elit porttitor nisi sollicitudin, eget porttitor odio tincidunt. Sed elit justo, suscipit non dui ut, eleifend euismod nibh. Nullam ac fermentum nisl. In convallis id leo sit amet eleifend. Suspendisse eu ligula pulvinar ex facilisis cursus ac ac velit. In ut turpis nec neque vehicula eleifend. Morbi in tempus est. Vivamus nisi nunc, pharetra quis scelerisque ut, tempor id dui.");
            textBox.AllowScrollBar = true;
            textBox.CurrentLine = 0;

            // add the textbox to the user interface
            OpenGL.UI.UserInterface.AddElement(textBox);

            // subscribe the escape event using the OpenGL.UI class library
            Input.Subscribe((char)27, Window.OnClose);

            // make sure to set up mouse event handlers for the window
            Window.OnMouseCallbacks.Add(OpenGL.UI.UserInterface.OnMouseClick);
            Window.OnMouseMoveCallbacks.Add(OpenGL.UI.UserInterface.OnMouseMove);

            while (Window.Open)
            {
                Window.HandleEvents();
                OnRenderFrame();
            }
        }

        private static void OnClose()
        {
            // make sure to dispose of everything
            OpenGL.UI.UserInterface.Dispose();
            OpenGL.UI.BMFont.Dispose();
            scrollTexture.Dispose();
        }

        private static void OnRenderFrame()
        {
            // set up the OpenGL viewport and clear both the color and depth bits
            Gl.Viewport(0, 0, Window.Width, Window.Height);
            Gl.ClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw the user interface after everything else
            OpenGL.UI.UserInterface.Draw();

            // finally, swap the back buffer to the front so that the screen displays
            Window.SwapBuffers();
        }
    }
}
