﻿Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.ComponentModel.Design

Public Class ToolStripManager
    Inherits ToolStripContainer

    Private _lastHeight As Integer = 0

    Public Event RendererChanged As EventHandler

    Public Sub New()
        _ContextMenuStrip = New ContextMenuStrip()

        'Assign ContextMenuStrip to all panels
        Me.TopToolStripPanel.ContextMenuStrip = _ContextMenuStrip
        Me.BottomToolStripPanel.ContextMenuStrip = _ContextMenuStrip
        Me.LeftToolStripPanel.ContextMenuStrip = _ContextMenuStrip
        Me.RightToolStripPanel.ContextMenuStrip = _ContextMenuStrip

        'Listen for the Opening event of the ContextMenuStrip so we can update it
        AddHandler _ContextMenuStrip.Opening, AddressOf ControlsChanged

        'Change the ContextMenuStrip items when ToolStrips are added/removed
        AddHandler TopToolStripPanel.ControlAdded, AddressOf ControlsChanged
        AddHandler TopToolStripPanel.ControlRemoved, AddressOf ControlsChanged
        AddHandler BottomToolStripPanel.ControlAdded, AddressOf ControlsChanged
        AddHandler BottomToolStripPanel.ControlRemoved, AddressOf ControlsChanged
        AddHandler LeftToolStripPanel.ControlAdded, AddressOf ControlsChanged
        AddHandler LeftToolStripPanel.ControlRemoved, AddressOf ControlsChanged
        AddHandler RightToolStripPanel.ControlAdded, AddressOf ControlsChanged
        AddHandler RightToolStripPanel.ControlRemoved, AddressOf ControlsChanged

        'Don't allow the top panel to resize to zero when no ToolStrips are present
        AddHandler TopToolStripPanel.SizeChanged, AddressOf TopPanelSizeChanged

        AddHandler TopToolStripPanel.RendererChanged, AddressOf PanelRendererChanged
        AddHandler BottomToolStripPanel.RendererChanged, AddressOf PanelRendererChanged
        AddHandler LeftToolStripPanel.RendererChanged, AddressOf PanelRendererChanged
        AddHandler RightToolStripPanel.RendererChanged, AddressOf PanelRendererChanged
    End Sub

    Private _menuStrips As List(Of MenuStrip) = New List(Of MenuStrip)
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
    Editor(GetType(MenuStripCollectionEditor), GetType(UITypeEditor))> _
    Public ReadOnly Property MenuStrips() As List(Of MenuStrip)
        Get
            Return _menuStrips
        End Get
    End Property

    Private _toolStrips As List(Of ToolStrip) = New List(Of ToolStrip)
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
    Editor(GetType(ToolStripCollectionEditor), GetType(UITypeEditor))> _
    Public ReadOnly Property ToolStrips() As List(Of ToolStrip)
        Get
            Return _toolStrips
        End Get
    End Property

    Private _ContextMenuStrip As ContextMenuStrip
    Public Overloads ReadOnly Property ContextMenuStrip() As ContextMenuStrip
        Get
            Return _ContextMenuStrip
        End Get
    End Property

    Public Property Renderer() As ToolStripRenderer
        Get
            Return TopToolStripPanel.Renderer
        End Get
        Set(ByVal value As ToolStripRenderer)
            TopToolStripPanel.Renderer = value
            OnRendererChanged(EventArgs.Empty)
        End Set
    End Property

    Private Sub ControlsChanged(ByVal sender As Object, ByVal e As EventArgs)
        ReloadContextMenu()
        MatchRenderers()
    End Sub

    Private Sub ReloadContextMenu()
        Me.ContextMenuStrip.Items.Clear()
        Dim item As ToolStripMenuItem
        'Loop through all ToolStrips contained in each of the four panels
        For Each ts As ToolStrip In Me.ToolStrips
            'Create new ToolStripMenuitem and check it if the TS is visible
            item = New ToolStripMenuItem(ts.Name, Nothing, AddressOf ContextMenuItemClicked)
            item.Checked = ts.Visible
            item.Tag = ts
            Me.ContextMenuStrip.Items.Add(item)
        Next
    End Sub

    Private Sub ContextMenuItemClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim item As ToolStripMenuItem = TryCast(sender, ToolStripMenuItem)
        If item IsNot Nothing Then
            Dim ts As ToolStrip = TryCast(item.Tag, ToolStrip)
            If ts IsNot Nothing Then
                ts.Visible = Not ts.Visible
                item.Checked = Not item.Checked
            End If
        End If
    End Sub

    Private Sub TopPanelSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
        If Me.TopToolStripPanel.Height = 0 Then
            Me.TopToolStripPanel.Height = _lastHeight
        Else
            _lastHeight = Me.TopToolStripPanel.Height
        End If
    End Sub

    Private Sub PanelRendererChanged(ByVal sender As Object, ByVal e As EventArgs)
        MatchRenderers()
    End Sub

    Public Overridable Sub OnRendererChanged(ByVal e As EventArgs)
        MatchRenderers()
        RaiseEvent RendererChanged(Me, e)
    End Sub

    Private Sub MatchRenderers()
        BottomToolStripPanel.Renderer = Me.Renderer
        LeftToolStripPanel.Renderer = Me.Renderer
        RightToolStripPanel.Renderer = Me.Renderer

        For Each ts As ToolStrip In Me.ToolStrips
            ts.Renderer = Me.Renderer
        Next
        For Each ms As MenuStrip In Me.MenuStrips
            ms.Renderer = Me.Renderer
        Next

        Me.ContextMenuStrip.Renderer = Me.Renderer
    End Sub

End Class

Public Class ToolStripCollectionEditor
    Inherits CollectionEditor

    Public Sub New(ByVal type As Type)
        MyBase.New(type)
    End Sub

    Protected Overrides Function CreateInstance(ByVal itemType As System.Type) As Object
        Dim host As IDesignerHost = DirectCast(Me.GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim ts As ToolStrip = CType(host.CreateComponent(itemType), ToolStrip)
        CType(Me.Context.Instance, ToolStripManager).TopToolStripPanel.Join(ts)
        Return ts
    End Function

End Class

Public Class MenuStripCollectionEditor
    Inherits CollectionEditor

    Public Sub New(ByVal type As Type)
        MyBase.New(type)
    End Sub

    Protected Overrides Function CreateInstance(ByVal itemType As System.Type) As Object
        Dim host As IDesignerHost = DirectCast(Me.GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim ms As MenuStrip = CType(host.CreateComponent(itemType), MenuStrip)
        CType(Me.Context.Instance, ToolStripManager).TopToolStripPanel.Join(ms)
        Return ms
    End Function

End Class