using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DoubleBuffer
{
    public partial class frm26DoubleBuffer : Form
    {
        public frm26DoubleBuffer()
        {
            InitializeComponent();
        }

        // Hilbert curve starting parameters.
        private int Depth = 0;
        private float StartLength, StartX, StartY;

        // Draw a Hilbert curve.
        private void drawButton_Click(object sender, EventArgs e)
        {
            // Get the depth of recursion.
            Depth = int.Parse(depthTextBox.Text);
            if (Depth > 8)
            {
                if (MessageBox.Show("A large depth may take a long time to draw (and will be mostly black anyway). Do you want to continue?",
                    "Continue?", MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question) == DialogResult.No) return;
            }

            // Double buffer if desired.
            DoubleBuffered = doubleBufferCheckBox.Checked;

            // Compute the side length for this level.
            StartX = depthTextBox.Right + 10;
            StartY = 10;
            StartLength = (float)(200 / (Math.Pow(2, Depth) - 1));

            // Draw the curve.
            Refresh();
        }

        // Draw the curve.
        private void frm26DoubleBuffer_Paint(object sender, PaintEventArgs e)
        {
            if (Depth < 1) return;

            e.Graphics.Clear(BackColor);
            LastX = (int)StartX;
            LastY = (int)StartY;
            Hilbert(e.Graphics, Depth, StartLength, 0);
        }

        // Draw a Hilbert curve.
        private void Hilbert(Graphics gr, int depth, float dx, float dy)
        {
            if (depth > 1) Hilbert(gr, depth - 1, dy, dx);
            DrawRelative(gr, dx, dy);
            if (depth > 1) Hilbert(gr, depth - 1, dx, dy);
            DrawRelative(gr, dy, dx);
            if (depth > 1) Hilbert(gr, depth - 1, dx, dy);
            DrawRelative(gr, -dx, -dy);
            if (depth > 1) Hilbert(gr, depth - 1, -dy, -dx);
        }

        // The end of the last segment drawn.
        private float LastX, LastY;

        // Draw the line (LastX, LastY)-(LastX + dx, LastY + dy) and
        // update LastX = LastX + dx, LastY = LastY + dy.
        private void DrawRelative(Graphics gr, float dx, float dy)
        {
            gr.DrawLine(Pens.Black, LastX, LastY, LastX + dx, LastY + dy);
            LastX = LastX + dx;
            LastY = LastY + dy;
        }


        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.drawButton = new System.Windows.Forms.Button();
            this.depthTextBox = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.doubleBufferCheckBox = new System.Windows.Forms.CheckBox();
            this.SuspendLayout();
            // 
            // drawButton
            // 
            this.drawButton.Location = new System.Drawing.Point(25, 90);
            this.drawButton.Name = "drawButton";
            this.drawButton.Size = new System.Drawing.Size(75, 23);
            this.drawButton.TabIndex = 2;
            this.drawButton.Text = "Draw";
            this.drawButton.UseVisualStyleBackColor = true;
            this.drawButton.Click += new System.EventHandler(this.drawButton_Click);
            // 
            // depthTextBox
            // 
            this.depthTextBox.Location = new System.Drawing.Point(57, 14);
            this.depthTextBox.Name = "depthTextBox";
            this.depthTextBox.Size = new System.Drawing.Size(55, 20);
            this.depthTextBox.TabIndex = 0;
            this.depthTextBox.Text = "5";
            this.depthTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 17);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(39, 13);
            this.label1.TabIndex = 8;
            this.label1.Text = "Depth:";
            // 
            // doubleBufferCheckBox
            // 
            this.doubleBufferCheckBox.AutoSize = true;
            this.doubleBufferCheckBox.Location = new System.Drawing.Point(12, 40);
            this.doubleBufferCheckBox.Name = "doubleBufferCheckBox";
            this.doubleBufferCheckBox.Size = new System.Drawing.Size(103, 17);
            this.doubleBufferCheckBox.TabIndex = 1;
            this.doubleBufferCheckBox.Text = "Double Buffered";
            this.doubleBufferCheckBox.UseVisualStyleBackColor = true;
            // 
            // frm26DoubleBuffer
            // 
            this.AcceptButton = this.drawButton;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(334, 221);
            this.Controls.Add(this.doubleBufferCheckBox);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.depthTextBox);
            this.Controls.Add(this.drawButton);
            this.Name = "frm26DoubleBuffer";
            this.Text = "DoubleBuffer";
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.frm26DoubleBuffer_Paint);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion
        private System.Windows.Forms.Button drawButton;
        private System.Windows.Forms.TextBox depthTextBox;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.CheckBox doubleBufferCheckBox;
    }
}