class CustomEditor(Editor):
    """ Custom style of editor for instances. If selection among instances is
    allowed, the editor displays a combo box listing instances that can be
    selected. If the current instance is editable, the editor displays a panel
    containing trait editors for all the instance's traits.
    """

    # Background color when an item can be dropped on the editor:
    ok_color = DropColor

    # The orientation of the instance editor relative to the instance selector:
    orientation = "vertical"

    # Class constant:
    extra = 0

    # ---------------------------------------------------------------------------
    #  Trait definitions:
    # ---------------------------------------------------------------------------

    # List of InstanceChoiceItem objects used by the editor
    items = Property

    # The view to use for displaying the instance
    view = AView

    # ---------------------------------------------------------------------------
    #  Finishes initializing the editor by creating the underlying toolkit
    #  widget:
    # ---------------------------------------------------------------------------

    def init(self, parent):
        """ Finishes initializing the editor by creating the underlying toolkit
            widget.
        """
        factory = self.factory
        if factory.name != "":
            self._object, self._name, self._value = self.parse_extended_name(factory.name)

        # Create a panel to hold the object trait's view:
        if factory.editable:
            self.control = self._panel = parent = SimplePanel()

        # Build the instance selector if needed:
        selectable = factory.selectable
        droppable = factory.droppable
        items = self.items
        for item in items:
            droppable |= item.is_droppable()
            selectable |= item.is_selectable()

        if selectable:
            self._object_cache = {}
            item = self.item_for(self.value)
            if item is not None:
                self._object_cache[id(item)] = self.value

            self._choice = ListBox()
            self._choice.setVisibleItemCount(0)

            self._choice.addChangeLister(getattr(self, "update_object"))

            self.set_tooltip(self._choice)

            if factory.name != "":
                self._object.on_trait_change(self.rebuild_items, self._name, dispatch="ui")
                self._object.on_trait_change(self.rebuild_items, self._name + "_items", dispatch="ui")

            factory.on_trait_change(self.rebuild_items, "values", dispatch="ui")
            factory.on_trait_change(self.rebuild_items, "values_items", dispatch="ui")

            self.rebuild_items()

        elif droppable:
            self._choice = TextBox()
            self._choice.setEnabled(False)
            self.set_tooltip(self._choice)

        #        if droppable:
        #            self._choice.SetDropTarget( PythonDropTarget( self ) )

        orientation = factory.orientation
        if orientation is "default":
            orientation = self.orientation

        if (selectable or droppable) and factory.editable:
            if orientation is "horizontal":
                panel = HorizontalPanel()
            else:
                panel = VerticalPanel()
            #            layout = QtGui.QBoxLayout(orientation, parent)
            #            layout.setMargin(0)
            #            layout.addWidget(self._choice)
            #
            #            if orientation == QtGui.QBoxLayout.TopToBottom:
            #                hline = QtGui.QFrame()
            #                hline.setFrameShape(QtGui.QFrame.HLine)
            #                hline.setFrameShadow(QtGui.QFrame.Sunken)
            #
            #                layout.addWidget(hline)

            self.create_editor(parent, panel)
        elif self.control is None:
            if self._choice is None:
                self._choice = ListBox()
                self._choice.setVisibleItemCount(0)
                self._choice.addChangeLister(getattr(self, "update_object"))

            self.control = self._choice
        else:
            if orientation is "horizontal":
                panel = HorizontalPanel()
            else:
                panel = VerticalPanel()
            self.create_editor(parent, panel)

        # Synchronize the 'view' to use:
        # fixme: A normal assignment can cause a crash (for unknown reasons) in
        # some cases, so we make sure that no notifications are generated:
        self.trait_setq(view=factory.view)
        self.sync_value(factory.view_name, "view", "from")

    # ---------------------------------------------------------------------------
    #  Creates the editor control:
    # ---------------------------------------------------------------------------

    def create_editor(self, parent, panel):
        """ Creates the editor control.
        """
        self._panel = SimplePanel()
        panel.addWidget(self._panel)

    # ---------------------------------------------------------------------------
    #  Gets the current list of InstanceChoiceItem items:
    # ---------------------------------------------------------------------------

    def _get_items(self):
        """ Gets the current list of InstanceChoiceItem items.
        """
        if self._items is not None:
            return self._items

        factory = self.factory
        if self._value is not None:
            values = self._value() + factory.values
        else:
            values = factory.values

        items = []
        adapter = factory.adapter
        for value in values:
            if not isinstance(value, InstanceChoiceItem):
                value = adapter(object=value)
            items.append(value)

        self._items = items

        return items

    # ---------------------------------------------------------------------------
    #  Rebuilds the object selector list:
    # ---------------------------------------------------------------------------

    def rebuild_items(self):
        """ Rebuilds the object selector list.
        """
        # Clear the current cached values:
        self._items = None

        # Rebuild the contents of the selector list:
        name = -1
        value = self.value
        choice = self._choice
        choice.clear()
        for i, item in enumerate(self.items):
            if item.is_selectable():
                choice.addItem(item.get_name())
                if item.is_compatible(value):
                    name = i

        # Reselect the current item if possible:
        if name >= 0:
            choice.setSelectedIndex(name)
        else:
            # Otherwise, current value is no longer valid, try to discard it:
            try:
                self.value = None
            except:
                pass

    # ---------------------------------------------------------------------------
    #  Returns the InstanceChoiceItem for a specified object:
    # ---------------------------------------------------------------------------

    def item_for(self, object):
        """ Returns the InstanceChoiceItem for a specified object.
        """
        for item in self.items:
            if item.is_compatible(object):
                return item

        return None

    # ---------------------------------------------------------------------------
    #  Returns the view to use for a specified object:
    # ---------------------------------------------------------------------------

    def view_for(self, object, item):
        """ Returns the view to use for a specified object.
        """
        view = ""
        if item is not None:
            view = item.get_view()

        if view == "":
            view = self.view

        return self.ui.handler.trait_view_for(self.ui.info, view, object, self.object_name, self.name)

    # ---------------------------------------------------------------------------
    #  Handles the user selecting a new value from the combo box:
    # ---------------------------------------------------------------------------

    def update_object(self, text):
        """ Handles the user selecting a new value from the combo box.
        """
        name = unicode(text)
        for item in self.items:
            if name == item.get_name():
                id_item = id(item)
                object = self._object_cache.get(id_item)
                if object is None:
                    object = item.get_object()
                    if (not self.factory.editable) and item.is_factory:
                        view = self.view_for(object, self.item_for(object))
                        view.ui(object, self.control, "modal")

                    if self.factory.cachable:
                        self._object_cache[id_item] = object

                self.value = object
                self.resynch_editor()
                break

    # ---------------------------------------------------------------------------
    #  Updates the editor when the object trait changes external to the editor:
    # ---------------------------------------------------------------------------

    def update_editor(self):
        """ Updates the editor when the object trait changes externally to the
            editor.
        """
        # Synchronize the editor contents:
        self.resynch_editor()

        # Update the selector (if any):
        choice = self._choice
        item = self.item_for(self.value)
        if (choice is not None) and (item is not None):
            name = item.get_name(self.value)
            if self._object_cache is not None:
                idx = choice.findText(name)
                for idx in range(choice.getItemCount()):
                    value = choice.getValue(idx)
                    if value == name:
                        break
                else:
                    idx = -1

                if idx < 0:
                    idx = choice.getItemCount()
                    choice.addItem(name)

                choice.setSelectedIndex(idx)
            else:
                choice.setItemText(name, choice.getSelectedIndex())

    # ---------------------------------------------------------------------------
    #  Resynchronizes the contents of the editor when the object trait changes
    #  external to the editor:
    # ---------------------------------------------------------------------------

    def resynch_editor(self):
        """ Resynchronizes the contents of the editor when the object trait
            changes externally to the editor.
        """
        panel = self._panel
        if panel is not None:
            # Dispose of the previous contents of the panel:
            layout = panel.layout()
            if layout is None:
                layout = VerticalPanel()
            #                layout.setMargin(0)
            elif self._ui is not None:
                self._ui.dispose()
                self._ui = None
            else:
                #                child = layout.takeAt(0)
                #                while child is not None:
                #                    child = layout.takeAt(0)
                #
                #                del child
                pass

            # Create the new content for the panel:
            stretch = 0
            value = self.value
            if not isinstance(value, HasTraits):
                str_value = ""
                if value is not None:
                    str_value = self.str_value
                control = Label(str_value)
            else:
                view = self.view_for(value, self.item_for(value))
                context = value.trait_context()
                handler = None
                if isinstance(value, Handler):
                    handler = value
                context.setdefault("context", self.object)
                context.setdefault("context_handler", self.ui.handler)
                self._ui = ui = view.ui(
                    context, panel, "subpanel", value.trait_view_elements(), handler, self.factory.id
                )
                control = ui.control
                self.scrollable = ui._scrollable
                ui.parent = self.ui

                if view.resizable or view.scrollable or ui._scrollable:
                    stretch = 1

            # FIXME: Handle stretch.
            layout.add(control)

    # ---------------------------------------------------------------------------
    #  Disposes of the contents of an editor:
    # ---------------------------------------------------------------------------

    def dispose(self):
        """ Disposes of the contents of an editor.
        """
        # Make sure we aren't hanging on to any object refs:
        self._object_cache = None

        if self._ui is not None:
            self._ui.dispose()

        if self._choice is not None:
            if self._object is not None:
                self._object.on_trait_change(self.rebuild_items, self._name, remove=True)
                self._object.on_trait_change(self.rebuild_items, self._name + "_items", remove=True)

            self.factory.on_trait_change(self.rebuild_items, "values", remove=True)
            self.factory.on_trait_change(self.rebuild_items, "values_items", remove=True)

        super(CustomEditor, self).dispose()

    # ---------------------------------------------------------------------------
    #  Handles an error that occurs while setting the object's trait value:
    # ---------------------------------------------------------------------------

    def error(self, excp):
        """ Handles an error that occurs while setting the object's trait value.
        """
        pass

    # ---------------------------------------------------------------------------
    #  Returns the editor's control for indicating error status:
    # ---------------------------------------------------------------------------

    def get_error_control(self):
        """ Returns the editor's control for indicating error status.
        """
        return self._choice or self.control

    # -- UI preference save/restore interface -----------------------------------

    # ---------------------------------------------------------------------------
    #  Restores any saved user preference information associated with the
    #  editor:
    # ---------------------------------------------------------------------------

    def restore_prefs(self, prefs):
        """ Restores any saved user preference information associated with the
            editor.
        """
        ui = self._ui
        if (ui is not None) and (prefs.get("id") == ui.id):
            ui.set_prefs(prefs.get("prefs"))

    # ---------------------------------------------------------------------------
    #  Returns any user preference information associated with the editor:
    # ---------------------------------------------------------------------------

    def save_prefs(self):
        """ Returns any user preference information associated with the editor.
        """
        ui = self._ui
        if (ui is not None) and (ui.id != ""):
            return {"id": ui.id, "prefs": ui.get_prefs()}

        return None

    # -- Traits event handlers --------------------------------------------------

    def _view_changed(self, view):
        self.resynch_editor()
class I2CPanel :
	
	class saveStateListener :
		def __init__(self, panel) :
			self._saveStatePanel=panel	
			
		def onRemoteResponse(self, response, request_info):
			self._saveStatePanel.returnStatement.setText("File saved:" + response)
			
		def onRemoteError(self, code, message, request_info):
			ErrorMessage( "Unable to contact server" )
			
	
	class loadStateListener :
		def __init__(self, panel) :
			self._saveStatePanel=panel	
			
		def onRemoteResponse(self, response, request_info):
			self._saveStatePanel.returnStatement.setText("File loaded:" + response)
			self._saveStatePanel.rpcService.I2CRegisterValues( self._saveStatePanel.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self._saveStatePanel) ) #refresh of text boxes

		def onRemoteError(self, code, message, request_info):
			ErrorMessage( "Unable to contact server" )
	
	class ConnectedCBCListener :
		"""
		A class to listen for the response to the connectedCBCNames call
		"""
		def __init__(self, listBox) :
			self.listBox=listBox
			
		def onRemoteResponse(self, response, request_info):
			self.listBox.clear()
			if response == None:
				self.listBox.addItem("<none>")
				self.listBox.setEnabled( False )
			else :
				for name in response :
					self.listBox.addItem(name) #e.g FE0CBC0
				self.listBox.setEnabled(True)

		def onRemoteError(self, code, message, request_info):
			ErrorMessage( "Unable to contact server" )

	class ReadRegisterValueListener :
		"""
		A class to listen for the response to the call to get the register values
		"""
		def __init__(self, panel) :
			self._I2Cpanel=panel
			self.textBoxes=self._I2Cpanel.i2cValueEntries
			
		def onRemoteResponse(self, response, request_info):
			#Call is now made for all connected CBCs for better stability of status box- fb
			for cbcName in self._I2Cpanel.getActiveCBCs():
				if cbcName=='FE0CBC0':
					valuesTuple = response[response.keys()[0]]
				elif cbcName=='FE0CBC1':
					valuesTuple = response[response.keys()[1]]
			# For this chip loop over all the register and set the text box values
			for registerName in valuesTuple :
				box=self.textBoxes[registerName]
				status=self._I2Cpanel.statusValueEntries[registerName]
				box.setText( "0x%02x"%valuesTuple[registerName] )
				box.setStyleAttribute( "background-color", "#FFFFFF" )
				box.setEnabled( True )
			#for some reason pyjas likes these separated - fb	
			for registerName in valuesTuple:
				if response['FE0CBC0'][registerName]==response['FE0CBC1'][registerName]:
					self._I2Cpanel.statusValueEntries[registerName].setText("==")
				else:
					self._I2Cpanel.statusValueEntries[registerName].setText(" //")
		def onRemoteError(self, code, message, request_info):
			ErrorMessage( "Unable to contact server" )

	class RefreshListener :
		"""
		A class that will wait for a response before refreshing the status box
		"""
		def __init__(self, panel) :
			self._Refresh = panel
		
		def onRemoteResponse(self, response, request_info):
			self._Refresh.rpcService.I2CRegisterValues( self._Refresh.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self._Refresh) )	 #Live refresh of the status box
			

		def onRemoteError(self, code, message, request_info):
			ErrorMessage( "Unable to contact server" )

	def __init__( self ) :
		# This is the service that will be used to communicate with the DAQ software
		self.rpcService = GlibRPCService.instance()
		# The main panel that everythings will be insided
		self.mainPanel = HorizontalPanel()
		self.mainPanel.setSpacing(10)
		self.i2cValueEntries = {} # The input boxes for all the registers
		self.statusValueEntries = {} # Displays the status of the i2cValueEntries
		
		self.stateValueEntries = {} # For load/save state
		self.fileName = {} # File name of the i2c registers
		
		# This is the list of available CBC chips. It will be populated by a call to the
		# server later.
		self.cbcList=ListBox(MultipleSelect=True, VisibleItemCount=10)
		self.cbcList.addItem( "waiting..." ) # Default text until I hear from the server what's connected
		self.cbcList.setEnabled( False )
		self.cbcList.addChangeListener(self)
		self.rpcService.connectedCBCNames( None, I2CPanel.ConnectedCBCListener(self.cbcList) ) # Ask the server what's connected
		
		
		# This is the panel that will have the list of I2C registers. I'll split up the
		# registers into subjects to make them more manageable.
		self.mainSettings = DisclosurePanel("Main Control Registers")
		self.channelMasks = DisclosurePanel("Channel Masks")
		self.channelTrims = DisclosurePanel("Channel Trims")
		self.callSettings = VerticalPanel("Load/Save States")
		self.callSettings.setBorderWidth(1)

		self.callSettings.add(HTML("<center>Load/Save State</center>"))
		
		cbcListAndCallSettings=VerticalPanel()
		cbcListAndCallSettings.add(self.cbcList)
		cbcListAndCallSettings.add(self.callSettings)
		self.mainPanel.add(cbcListAndCallSettings)
		self.mainPanel.add(self.mainSettings)
		self.mainPanel.add(self.channelMasks)
		self.mainPanel.add(self.channelTrims)
		
		self.callSettings.add( self.createStatesPanel())
		self.mainSettings.add( self.createRegisterPanel(["FrontEndControl","TriggerLatency","HitDetectSLVS","Ipre1","Ipre2","Ipsf","Ipa","Ipaos","Vpafb","Icomp","Vpc","Vplus","VCth","TestPulsePot","SelTestPulseDel&ChanGroup","MiscTestPulseCtrl&AnalogMux","TestPulseChargePumpCurrent","TestPulseChargeMirrCascodeVolt","CwdWindow&Coincid","MiscStubLogic"]) )
		self.channelMasks.add( self.createRegisterPanel(["MaskChannelFrom008downto001","MaskChannelFrom016downto009","MaskChannelFrom024downto017","MaskChannelFrom032downto025","MaskChannelFrom040downto033","MaskChannelFrom048downto041","MaskChannelFrom056downto049","MaskChannelFrom064downto057","MaskChannelFrom072downto065","MaskChannelFrom080downto073","MaskChannelFrom088downto081","MaskChannelFrom096downto089","MaskChannelFrom104downto097","MaskChannelFrom112downto105","MaskChannelFrom120downto113","MaskChannelFrom128downto121","MaskChannelFrom136downto129","MaskChannelFrom144downto137","MaskChannelFrom152downto145","MaskChannelFrom160downto153","MaskChannelFrom168downto161","MaskChannelFrom176downto169","MaskChannelFrom184downto177","MaskChannelFrom192downto185","MaskChannelFrom200downto193","MaskChannelFrom208downto201","MaskChannelFrom216downto209","MaskChannelFrom224downto217","MaskChannelFrom232downto225","MaskChannelFrom240downto233","MaskChannelFrom248downto241","MaskChannelFrom254downto249"]) )
		self.channelTrims.add( self.createRegisterPanel(["Channel001","Channel002","Channel003","Channel004","Channel005","Channel006","Channel007","Channel008","Channel009","Channel010","Channel011","Channel012","Channel013","Channel014","Channel015","Channel016","Channel017","Channel018","Channel019","Channel020","Channel021","Channel022","Channel023","Channel024","Channel025","Channel026","Channel027","Channel028","Channel029","Channel030","Channel031","Channel032","Channel033","Channel034","Channel035","Channel036","Channel037","Channel038","Channel039","Channel040","Channel041","Channel042","Channel043","Channel044","Channel045","Channel046","Channel047","Channel048","Channel049","Channel050","Channel051","Channel052","Channel053","Channel054","Channel055","Channel056","Channel057","Channel058","Channel059","Channel060","Channel061","Channel062","Channel063","Channel064","Channel065","Channel066","Channel067","Channel068","Channel069","Channel070","Channel071","Channel072","Channel073","Channel074","Channel075","Channel076","Channel077","Channel078","Channel079","Channel080","Channel081","Channel082","Channel083","Channel084","Channel085","Channel086","Channel087","Channel088","Channel089","Channel090","Channel091","Channel092","Channel093","Channel094","Channel095","Channel096","Channel097","Channel098","Channel099","Channel100","Channel101","Channel102","Channel103","Channel104","Channel105","Channel106","Channel107","Channel108","Channel109","Channel110","Channel111","Channel112","Channel113","Channel114","Channel115","Channel116","Channel117","Channel118","Channel119","Channel120","Channel121","Channel122","Channel123","Channel124","Channel125","Channel126","Channel127","Channel128","Channel129","Channel130","Channel131","Channel132","Channel133","Channel134","Channel135","Channel136","Channel137","Channel138","Channel139","Channel140","Channel141","Channel142","Channel143","Channel144","Channel145","Channel146","Channel147","Channel148","Channel149","Channel150","Channel151","Channel152","Channel153","Channel154","Channel155","Channel156","Channel157","Channel158","Channel159","Channel160","Channel161","Channel162","Channel163","Channel164","Channel165","Channel166","Channel167","Channel168","Channel169","Channel170","Channel171","Channel172","Channel173","Channel174","Channel175","Channel176","Channel177","Channel178","Channel179","Channel180","Channel181","Channel182","Channel183","Channel184","Channel185","Channel186","Channel187","Channel188","Channel189","Channel190","Channel191","Channel192","Channel193","Channel194","Channel195","Channel196","Channel197","Channel198","Channel199","Channel200","Channel201","Channel202","Channel203","Channel204","Channel205","Channel206","Channel207","Channel208","Channel209","Channel210","Channel211","Channel212","Channel213","Channel214","Channel215","Channel216","Channel217","Channel218","Channel219","Channel220","Channel221","Channel222","Channel223","Channel224","Channel225","Channel226","Channel227","Channel228","Channel229","Channel230","Channel231","Channel232","Channel233","Channel234","Channel235","Channel236","Channel237","Channel238","Channel239","Channel240","Channel241","Channel242","Channel243","Channel244","Channel245","Channel246","Channel247","Channel248","Channel249","Channel250","Channel251","Channel252","Channel253","Channel254","ChannelDummy"]) )
		
		self.mainSettings.add()
		self.echo=Label()
		self.mainPanel.add(self.echo)

	def getPanel( self ) :
		return self.mainPanel
	
	def onChange( self, sender ) :
		
		if sender == self.cbcList :
			# Make a call to the RPC service to get the register values
			self.rpcService.I2CRegisterValues( self.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self) )#fb - sends all CBCs
			self.load.setEnabled(True)
			self.save.setEnabled(True)
		elif sender == self.save:
			msg = self.saveFileName.getText()
			self.rpcService.saveI2cRegisterValues(msg, I2CPanel.saveStateListener(self) )
		elif sender == self.load:
			msg = self.loadFileName.getText()
			self.rpcService.loadI2cRegisterValues(msg, I2CPanel.loadStateListener(self) )	
			self.rpcService.I2CRegisterValues( self.getTotalCBCs(), I2CPanel.ReadRegisterValueListener(self) )#
				
		# Sender must be a text box. Need to format the input.
		else : 
			try:
			# For some reason the '0x' at the start of the string is causing exceptions,
			# even though it works fine with interactive python. I'll take it off anyway.
				string=sender.getText()
				if( len(string)>=2 ) :
					if string[0]=='0' and string[1]=='x' : string=string[2:]
					value=int( string, 16 ) # convert as hex
					# Cap values at 255
					if value<0 : value=0
					if value>255 : value=255
					sender.setStyleAttribute( "background-color", "#FFFFFF" )
			# Convert to the same format as everything else
				sender.setText( "0x%02x"%value )
			# Send the change to the RPC service
				messageParameters = {}
				for cbcName in self.getActiveCBCs() :
					messageParameters[cbcName]={ sender.getTitle():value }
					self.rpcService.setI2CRegisterValues( messageParameters, I2CPanel.RefreshListener(self) )
			
			except ValueError:
				sender.setStyleAttribute( "background-color", "#FF3333" )		
		
		#self.echoSelection()
	
	def echoSelection(self): #fb - a good "print screen" method
		msg = " File saved: "
		for names in self.getCheckedStates():
			msg += names
		self.echo.setText(msg)	
			
	def getList(self):
		selectCBCs = []
		for i in range(self.cbcList.getItemCount()) :
			if self.cbcList.isItemSelected(i):
				selectedCBCs.append(self.cbcList.getItemText(i))
				
	def getTotalCBCs(self) : #fb
		totalCBCs = []
		for i in range(self.cbcList.getItemCount()) :
			totalCBCs.append(self.cbcList.getItemText(i))
		return totalCBCs
	
	def getSpecificCBC(self, i): #fb
		specificCBC = []
		specificCBC.append(self.cbcList.getItemText(i))
		return specificCBC
		

	def getActiveCBCs(self) :
		selectedCBCs = []
		for i in range(self.cbcList.getItemCount()) :
			if self.cbcList.isItemSelected(i):
				selectedCBCs.append(self.cbcList.getItemText(i))
		return selectedCBCs
	
	def getCheckedStates(self): # returns the checked boxes + filename
		selectedStates = []
		#for names in self.stateValueEntries:
			#if str(self.stateValueEntries[names].isChecked())=="True":
			#	selectedStates.append(names)
		selectedStates.append(self.saveFileName.getText())
		return selectedStates
		
	def createRegisterPanel( self, registerNames ) :
		"""
		Creates panels and buttons for everything given in registerNames, and returns the main panel.
		"""
		flowPanel=FlowPanel()
		for buttonName in registerNames :
			newPanel=HorizontalPanel()
			label=Label(buttonName)
			newPanel.add( label )
			newTextBox=TextBox()
			newTextBox.setEnabled(False)
			newTextBox.setWidth(80)
			statusBox=TextBox()
			statusBox.setEnabled(False)
			statusBox.setWidth(30)
			newPanel.add(newTextBox)
			newPanel.add(statusBox)
			newPanel.setCellHorizontalAlignment( newTextBox, HasHorizontalAlignment.ALIGN_RIGHT )
			newPanel.setCellHorizontalAlignment( statusBox, HasHorizontalAlignment.ALIGN_RIGHT )
			newPanel.setCellWidth( statusBox, "20px" )
			newPanel.setWidth("100%")
			#newPanel.setStyleName("areaStyle");
			#newPanel.setBorderWidth(5);
			
			newTextBox.setText("select chip...")
			newTextBox.addChangeListener(self)
			newTextBox.setTitle(buttonName) # This isn't displayed, but it's useful to have stored
			
			self.i2cValueEntries[buttonName]=newTextBox	
			
			self.statusValueEntries[buttonName]=statusBox
			statusBox.setTitle(buttonName)
			statusBox.setText("...")
			
			flowPanel.add(newPanel)


		return flowPanel
	
	def createStatesPanel(self):
		vertPanel=VerticalPanel()
		vertPanel.setSpacing(10)
		
		selectionNames = (["Main Control", "Masks", "Trims"])	
		registerSelection = VerticalPanel()
		
		for name in selectionNames :
			checkBox = CheckBox(name)
			checkBox.setTitle(name)
			self.stateValueEntries[name]=checkBox
			registerSelection.add(checkBox)
		
		#Tidy up 
		loadPanel = HorizontalPanel()
		loadFileTextBox = TextBox()
		loadFileTextBox.setText("MyI2cCfg")
		loadFileTextBox.setWidth(80)
		self.loadFileName = loadFileTextBox
		loadPanel.add(loadFileTextBox)
		self.load = Button("Load",getattr(self,"onChange")) #overrides default and sends it to onChange
		loadPanel.add(self.load)
		self.load.setEnabled(False)
		
		savePanel = HorizontalPanel()
		saveFileTextBox = TextBox()
		saveFileTextBox.setText("MyI2cCfg")
		saveFileTextBox.setWidth(80)
		self.saveFileName = saveFileTextBox
		savePanel.add(saveFileTextBox)
		self.save = Button("Save", getattr(self,"onChange"))
		savePanel.add(self.save)
		self.save.setEnabled(False)
		
		self.returnStatement = Label()
		
		vertPanel.add(registerSelection)
		vertPanel.add(loadPanel)
		vertPanel.add(savePanel)
		vertPanel.add(self.returnStatement)
		
		return vertPanel
class DisplayHistogramsView(object) :
	"""
	@brief View in the MVP pattern for displaying histograms.

	@author Mark Grimes ([email protected])
	@date 09/Feb/2014
	"""
	def __init__( self ) :
		self.cbcList=ListBox(MultipleSelect=True, VisibleItemCount=4)
		self.channelList=ListBox(MultipleSelect=True, VisibleItemCount=20)
		self.updateButton=Button("Update")

		controls=VerticalPanel()
		controls.add(self.updateButton)
		controls.add(self.cbcList)
		controls.add(self.channelList)

		controls.setCellHorizontalAlignment( self.updateButton, HasHorizontalAlignment.ALIGN_CENTER )
		self.cbcList.setWidth("95%")
		self.channelList.setWidth("95%")

		self.cbcList.addItem( "waiting..." )
		for index in range(0,254) :
			self.channelList.addItem( "Channel %3d"%index )

		self.histogram = Image()
		self.mainPanel = HorizontalPanel()
		self.mainPanel.add( controls )
		self.mainPanel.add( self.histogram )
		self.histogram.setUrl( "defaultScurveHistogram.png" )

	def getPanel( self ) :
		return self.mainPanel

	def setAvailableCBCs( self, cbcNames ) :
		self.cbcList.clear()
		for name in cbcNames :
			self.cbcList.addItem( name )

	def enable( self ) :
		self.updateButton.setEnabled(True)
		self.cbcList.setEnabled(True)
		self.channelList.setEnabled(True)

	def disable( self ) :
		self.updateButton.setEnabled(False)
		self.cbcList.setEnabled(False)
		self.channelList.setEnabled(False)
	
	def getUpdateButton( self ) :
		return self.updateButton
	
	def getSelectedCBCChannels( self ) :
		"""
		Returns a dictionary of which channels are selected, with CBC name as a key and
		an array of the channels for that CBC as the value.
		"""
		# The way this view is currently set up, the selected channels have to be the same
		# for each selected CBC.
		selectedChannels=[]
		for index in range(self.channelList.getItemCount()) :
			if self.channelList.isItemSelected(index) :
				selectedChannels.append(index)
		returnValue={}
		for index in range(self.cbcList.getItemCount()) :
			if self.cbcList.isItemSelected(index) : returnValue[self.cbcList.getItemText(index)]=selectedChannels

		return returnValue

	def setImage( self, url ) :
		self.histogram.setUrl( url )