def __init__(self,parent,attribute):
        super(_list_wx_widget,self).__init__(parent,-1)
        self.attribute = attribute
        self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.newbutton = wx.Button(self,self.__class__.ID_APPENDBUTTON,label="Append")
        sizer.Add(self.newbutton)
        wx.EVT_BUTTON(self,self.__class__.ID_APPENDBUTTON,self.onAppend)
        self.notifyclosure = NotifyClosure(self,self.node_changed)
        self.notifyclosure.register(self.attribute)

        i = 0
        for element in attribute:
            sizer.Add(_listitem_wx_widget(self,element,i))
            i += 1
    def buildUi(self):
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.title = wx.StaticText(self,ID_LABEL)
        self.title.SetLabel(repr(self.obj) +" - \"" +str(self.obj)+"\"") 
        self.sizer.Add(self.title,0)

        #Walk down the inheritance hierachy Finding each object.
        current = self.obj
        done = []
        while current is not None:
            print repr(current)
            panel, included  = self._buildObjectPanel(current,done,self.obj)
            self.sizer.Add(panel,0,wx.EXPAND)
            done += included
            #Hide empty panel - but leave them to simply our sync algorithm
            if not included:  panel.Show(False)
            current = current.get_parent()
        
        self.notify = NotifyClosure(self,self.node_changed)
        self.notify.register(self.obj)
class ObjectPanel(wx.PyPanel):
    def __init__(self,parent,obj):
        super(ObjectPanel,self).__init__(parent,-1,wx.DefaultPosition,wx.Size(0,0))
        self.obj = obj
        self.buildUi()
        self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
        self.TransferDataToWindow()
        self.Layout()
        self.SetAutoLayout(True)

    def getPanelName(self):
        return repr(self.obj)

    def buildUi(self):
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.title = wx.StaticText(self,ID_LABEL)
        self.title.SetLabel(repr(self.obj) +" - \"" +str(self.obj)+"\"") 
        self.sizer.Add(self.title,0)

        #Walk down the inheritance hierachy Finding each object.
        current = self.obj
        done = []
        while current is not None:
            print repr(current)
            panel, included  = self._buildObjectPanel(current,done,self.obj)
            self.sizer.Add(panel,0,wx.EXPAND)
            done += included
            #Hide empty panel - but leave them to simply our sync algorithm
            if not included:  panel.Show(False)
            current = current.get_parent()
        
        self.notify = NotifyClosure(self,self.node_changed)
        self.notify.register(self.obj)

    def node_changed(self,node):
        self.TransferDataToWindow()

    def _syncUi(self):
        current = self.obj
        done = []
        for base_panel in self.GetChildren():
            if not isinstance(base_panel,_object_section): continue
            panel_obj = base_panel.get_object()
            
            if current is not panel_obj:
                #What exaclty ? Hmm.
                #This mean we're out of touch with the parent seq.
                #And we need to rewrite the sequence from here down.
                raise RuntimeError("NYI: Parent heirachy change detected")
            else:
                done_in_current =  [ ]
                for attrib_panel in base_panel.GetChildren():
                    if not isinstance(attrib_panel,_attribute_section): continue
                    attribute = attrib_panel.attribute
                    #If the attribute has been removed or overridden remove the panel.
                    if (attribute.name not in current) or (attribute.name in done):
                        base_panel.remove(attrib_panel)
                    else: done_in_current += [ attribute.name ]
                #Add panels for new attributes..
                done += done_in_current
                for attrib_obj in current:
                    if attrib_obj.name in done: continue
                    base_panel.add(_attribute_section(base_panel,-1,attrib_obj,self.obj))

            current = current.get_parent()

    def TransferDataToWindow(self):
        #TODO: Walk thru attributes and hide/show  overridden and new sections
        self._syncUi()
        super(ObjectPanel,self).TransferDataToWindow()
        self.Layout()

    def _buildObjectPanel(self,obj,overridden_list,top_object):
        section = _object_section(self,obj,overridden_list,top_object)
        return section, section.get_included()
class _list_wx_widget(wx.PyPanel):
    ID_APPENDBUTTON = NewUI_ID()
    def __init__(self,parent,attribute):
        super(_list_wx_widget,self).__init__(parent,-1)
        self.attribute = attribute
        self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.newbutton = wx.Button(self,self.__class__.ID_APPENDBUTTON,label="Append")
        sizer.Add(self.newbutton)
        wx.EVT_BUTTON(self,self.__class__.ID_APPENDBUTTON,self.onAppend)
        self.notifyclosure = NotifyClosure(self,self.node_changed)
        self.notifyclosure.register(self.attribute)

        i = 0
        for element in attribute:
            sizer.Add(_listitem_wx_widget(self,element,i))
            i += 1

    def node_changed(self,obj):
        i =0 
        sizer = self.GetSizer()
        #Use list comprehension to copy elements into a list
        # - ignore the first (append button) element of the list display objects
        display_items = [ x.GetWindow() for x in sizer.GetChildren()][1:]
        index_elements = [x for x in self.attribute]

        element = _pop(index_elements)
        child   = _pop(display_items)
        while (element is not None) or (child is not None):
       
            cname = child and child.get_stableindex()
            #Can't use the boolean eval trick to protect elements
            # against None, because they may test as false for their own
            # reasonns . Or may have no boolean conversion
            nname = element
            if element is not None: nname = nname.name

            if nname == cname:
                #Node in place in tree already, move on to next
                # but we may need to update it's index positions.
                child.set_index(i)
                element = _pop(index_elements)
                child   = _pop(display_items)
                i += 1
            elif _compare_names_lt(nname,cname):
               #Insert item
                newpanel=_listitem_wx_widget(self,element,i)
                sizer.Insert(i+1,newpanel)
                newpanel.TransferDataToWindow()
                i+=1
                element = _pop(index_elements)
            else:
                # Remove item.
                child.Destroy()
                child   = _pop(display_items)
                    
        self.GetTopLevelParent().Layout()

 
    def onAppend(self,evt):
       from dialogs.newattribute import NewAttributeDialog
       dlg = NewAttributeDialog(self,-1,owner = self.attribute ,title ="Enter initial value",
                                write = "append")
       dlg.Show()