Public Class ColorPalette
    Inherits System.Windows.Forms.UserControl
    ' members...
    Public Buttons As New ArrayList()
    Public ButtonSize As Integer = 15
    Public ButtonSpacing As Integer = 5
    Public LeftColor As Color = Color.Black
    Public RightColor As Color = Color.White

    Private leftButton As ColorPaletteButton
    Private rightButton As ColorPaletteButton

    ' AddColor - add a new color button to the control...

    ' events...
    Event LeftClick(ByVal sender As Object, ByVal e As EventArgs)
    Event RightClick(ByVal sender As Object, ByVal e As EventArgs)
    Public Function GetButtonAt(ByVal x As Integer, ByVal y As Integer) _
                           As ColorPaletteButton

        ' go through each button in turn...
        Dim button As ColorPaletteButton
        For Each button In Buttons

            ' is this button in the rectangle...
            If button.Rectangle.Contains(x, y) = True Then Return button

        Next

    End Function

    Public Function AddColor(ByVal newColor As Color) As _
           ColorPaletteButton

        ' create the button...
        Dim button As New ColorPaletteButton(newColor)

        ' add it to the list...
        Buttons.Add(button)

    End Function

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        ' add the colors...
        AddColor(Color.Black)
        AddColor(Color.White)
        AddColor(Color.Red)
        AddColor(Color.Blue)
        AddColor(Color.Green)
        AddColor(Color.Gray)
        AddColor(Color.DarkRed)
        AddColor(Color.DarkBlue)
        AddColor(Color.DarkGreen)
        AddColor(Color.DarkGray)
        AddColor(Color.FromArgb(208, 112, 222))
        AddColor(CType(SystemBrushes.ActiveCaption, SolidBrush).Color)
    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents dlgColor As System.Windows.Forms.ColorDialog
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.dlgColor = New System.Windows.Forms.ColorDialog()
        '
        'ColorPalette
        '
        Me.Name = "ColorPalette"

    End Sub

#End Region

    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        ' variables to hold the position...
        Dim x As Integer, y As Integer

        ' go through the array and position the buttons...
        Dim button As ColorPaletteButton
        For Each button In Buttons

            ' position the button...
            button.SetPosition(x, y, ButtonSize)

            ' move for the next one...
            x += (ButtonSize + ButtonSpacing)

            ' do we need to go down to the next row?
            If x + ButtonSize > Width Then

                ' move y...
                y += (ButtonSize + ButtonSpacing)

                ' reset x...
                x = 0

            End If

        Next

        ' redraw...
        Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        ' loop through...
        Dim button As ColorPaletteButton
        For Each button In Buttons

            ' do we need to draw?
            If e.ClipRectangle.IntersectsWith(button.Rectangle) Then
                button.Draw(e.Graphics)
            End If

        Next

    End Sub

    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        ' find the button that we clicked on...
        Dim button As ColorPaletteButton = GetButtonAt(e.X, e.Y)
        If Not button Is Nothing Then

            ' select this color...
            If e.Button = MouseButtons.Left Then
                ' make sure that this button is not the current right...
                If Not button Is rightButton Then

                    ' set the color...
                    LeftColor = button.Color
                    ' clear the existing selection...
                    If Not leftButton Is Nothing Then
                        leftButton.ButtonAssignment = _
                            ColorPaletteButton.ButtonAssignments.None
                        Invalidate(leftButton.Rectangle)
                    End If

                    ' mark the button...
                    button.ButtonAssignment = _
                        ColorPaletteButton.ButtonAssignments.LeftButton
                    Invalidate(button.Rectangle)
                    leftButton = button

                    ' fire the event...
                    RaiseEvent LeftClick(Me, New EventArgs())

                End If
            End If
            ' did we click with the right?
            If e.Button = MouseButtons.Right Then
                ' make sure this button is not the current left...
                If Not button Is leftButton Then

                    ' set right color...
                    RightColor = button.Color
                    ' clear the existing selection...
                    If Not rightButton Is Nothing Then
                        rightButton.ButtonAssignment = _
                            ColorPaletteButton.ButtonAssignments.None
                        Invalidate(rightButton.Rectangle)
                    End If

                    ' mark the button...
                    button.ButtonAssignment = _
                        ColorPaletteButton.ButtonAssignments.RightButton
                    Invalidate(button.Rectangle)
                    rightButton = button

                    ' fire the event...
                    RaiseEvent RightClick(Me, New EventArgs())

                End If
            End If
        Else

            ' display the color dialog...
            If dlgColor.ShowDialog = DialogResult.OK Then

                ' add the new color...
                AddColor(dlgColor.Color)

                ' resize the palette to show the dialog...
                OnResize(New EventArgs())

            End If


        End If

    End Sub
End Class
