import wx

METHOD = 2

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        self.panel = wx.Panel(self)

        self.initial_message = "label"

        sizer = wx.BoxSizer()

        self.text = wx.TextCtrl(self.panel, value=self.initial_message)
        sizer.Add(self.text, 0, wx.ALL, 5)
        self.button = wx.Button(self.panel, label="Update")
        sizer.Add(self.button, 0, wx.ALL, 5)

        self.panel.SetSizer(sizer)

        # self.CreateTabs((
        #     ("Tab one", wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_TOOLBAR, (32, 32))),
        #     ("Tab two", wx.ArtProvider.GetBitmap(wx.ART_CDROM, wx.ART_TOOLBAR, (32, 32))),
        # ))
        self.CreateTabs()

        self.button.Bind(wx.EVT_BUTTON, self.OnButton)
        self.i = 1
        self.Show()

    def OnButton(self, event):
        text_value = self.text.GetValue()
        self.label.SetLabel(text_value)
        if METHOD == 1:
            # Doesn't seem to have an effect?
            self.toolbar.Realize()
        elif METHOD == 2:
            # For some reason a combination of AddControl and resizing results in the desired effect
            # Although this then breaks toolbar.RemoveTool and toolbar.ClearTools :(
            self.toolbar.AddControl(self.label)
            self.SetSize((400 + self.i,400) )
            self.i += 1
        elif METHOD == 3:
            # This works but unfortunately because of the visual effect of the toolbar disappearing and reappearing
            # I can't use this method :(
            # Is there a way to make it not animate between ClearTools and adding the tools again ?
            self.toolbar.ClearTools()
            self.MakeTools(text_value)


    def MakeTools(self, label=""):
        tabs = (
            ("Tab one", wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_TOOLBAR, (32, 32))),
            ("Tab two", wx.ArtProvider.GetBitmap(wx.ART_CDROM, wx.ART_TOOLBAR, (32, 32))),
        )

        self.label = wx.StaticText(self.toolbar, label=label)
        self.toolbar.AddControl(self.label)

        for i, (label, bitmap) in enumerate(tabs):
            self.toolbar.AddCheckLabelTool(id=i, label=label, bitmap=bitmap)
        self.toolbar.Realize()

    def CreateTabs(self):
        """
        Create the toolbar and add a tool for each tab.

        tabs -- List of (label, bitmap) pairs.
        """

        # Create the toolbar
        self.tabIndex = 1
        self.toolbar = self.CreateToolBar(style=wx.TB_HORIZONTAL|wx.TB_TEXT)

        self.MakeTools(self.initial_message)

        # Determine whether to invoke the special toolbar handling
        macNative = False
        if wx.Platform == '__WXMAC__':
            if hasattr(self, 'MacGetTopLevelWindowRef'):
                try:
                    import ctypes
                    macNative = True
                except ImportError:
                    pass
        if macNative:
            self.PrepareMacNativeToolBar()
            self.Bind(wx.EVT_TOOL, self.OnToolBarMacNative)
        else:
            self.toolbar.ToggleTool(0, True)
            self.Bind(wx.EVT_TOOL, self.OnToolBarDefault)

        self.Show()

    def OnTabChange(self, tabIndex):
        """Respond to the user switching tabs."""

        pass

    def PrepareMacNativeToolBar(self):
        """Extra toolbar setup for OS X native toolbar management."""

        # Load the frameworks
        import ctypes
        carbonLoc = '/System/Library/Carbon.framework/Carbon'
        coreLoc = '/System/Library/CoreFoundation.framework/CoreFoundation'
        self.carbon = ctypes.CDLL(carbonLoc)  # Also used in OnToolBarMacNative
        core = ctypes.CDLL(coreLoc)
        # Get a reference to the main window
        frame = self.MacGetTopLevelWindowRef()
        # Allocate a pointer to pass around
        p = ctypes.c_voidp()
        # Get a reference to the toolbar
        self.carbon.GetWindowToolbar(frame, ctypes.byref(p))
        toolbar = p.value
        # Get a reference to the array of toolbar items
        self.carbon.HIToolbarCopyItems(toolbar, ctypes.byref(p))
        # Get references to the toolbar items (note: separators count)
        self.macToolbarItems = [core.CFArrayGetValueAtIndex(p, i)
                                for i in xrange(self.toolbar.GetToolsCount())]
        # Set the native "selected" state on the first tab
        # 128 corresponds to kHIToolbarItemSelected (1 << 7)
        item = self.macToolbarItems[self.tabIndex]
        self.carbon.HIToolbarItemChangeAttributes(item, 128, 0)

    def OnToolBarDefault(self, event):
        """Ensure that there is always one tab selected."""

        i = event.GetId()
        if i in xrange(self.toolbar.GetToolsCount()):
            self.toolbar.ToggleTool(i, True)
            if i != self.tabIndex:
                self.toolbar.ToggleTool(self.tabIndex, False)
                self.OnTabChange(i)
                self.tabIndex = i
        else:
            event.Skip()

    def OnToolBarMacNative(self, event):
        """Manage the toggled state of the tabs manually."""

        i = event.GetId()
        ii = i + 1
        if ii in xrange(self.toolbar.GetToolsCount()):
            self.toolbar.ToggleTool(i, False)  # Suppress default selection
            if ii != self.tabIndex:
                # Set the native selection look via the Carbon APIs
                # 128 corresponds to kHIToolbarItemSelected (1 << 7)
                item = self.macToolbarItems[ii]
                self.carbon.HIToolbarItemChangeAttributes(item, 128, 0)
                self.OnTabChange(i)
                self.tabIndex = ii
        else:
            event.Skip()

if __name__ == "__main__":
    app = wx.App(False)
    Frame()
    app.MainLoop()