# HG changeset patch # User laurent # Date 1250259979 -7200 # Node ID 5c0f34a9ab00dacdd0f27bd33f6f0544e1a46023 # Parent 46d7d2ce84d2a54fdb763be19db5f9bf2b21ba10 Improving support for svgui, separating setting end getting attributes functions from creating function. diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 Beremiz_service.py --- a/Beremiz_service.py Thu Aug 13 11:48:55 2009 +0200 +++ b/Beremiz_service.py Fri Aug 14 16:26:19 2009 +0200 @@ -509,16 +509,26 @@ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> ''' - - class DefaultPLCStartedHMI(athena.LiveElement): + class PLCHMI(athena.LiveElement): + + initialised = False + + def HMIinitialised(self, result): + self.initialised = True + + def HMIinitialisation(self): + self.HMIinitialised(None) + + class DefaultPLCStartedHMI(PLCHMI): docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ tags.h1["PLC IS NOW STARTED"], ]) - class PLCStoppedHMI(athena.LiveElement): + + class PLCStoppedHMI(PLCHMI): docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ tags.h1["PLC IS STOPPED"] ]) - + class MainPage(athena.LiveElement): jsClass = u"WebInterface.PLC" docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ @@ -583,6 +593,7 @@ tags.div( render = tags.directive( "MainPage" )) ]]]]) MainPage = MainPage() + PLCHMI = PLCHMI def __init__(self, plcState=False, *a, **kw): super(WebInterface, self).__init__(*a, **kw) diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 plugins/python/modules/svgui/livesvg.js --- a/plugins/python/modules/svgui/livesvg.js Thu Aug 13 11:48:55 2009 +0200 +++ b/plugins/python/modules/svgui/livesvg.js Fri Aug 14 16:26:19 2009 +0200 @@ -1,14 +1,11 @@ // import Nevow.Athena // import Divmod.Base -function init() { - Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'initClient'); -} function updateAttr(id, param, value) { Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value); } -var svguiWidgets={}; +var svguiWidgets = new Array(); var currentObject = null; function setCurrentObject(obj) { @@ -28,6 +25,7 @@ LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget'); LiveSVGPage.LiveSVGWidget.methods( + function handleEvent(self, evt) { if (currentObject != null) { currentObject.handleEvent(evt); @@ -36,28 +34,20 @@ function receiveData(self, data){ dataReceived = json_parse(data); - newState = json_parse(dataReceived.kwargs).state - svguiWidgets[dataReceived.back_id].updateState(newState); + gadget = svguiWidgets[dataReceived.id] + if (gadget) { + gadget.updateValues(json_parse(dataReceived.kwargs)); + } //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState); }, - function SvguiButton(self,elt_back, args){ - var btn = new svguilib.button(self, elt_back, args.sele_id, args.toggle, args.state, args.active); - return btn; - }, - - function SvguiTextCtrl(self, elt_back, args){ - var txtCtrl = new svguilib.textControl(self, elt_back, args.state); - return txtCtrl; - }, - function init(self, arg1){ //console.log("Object received : " + arg1); for (ind in arg1) { gad = json_parse(arg1[ind]); args = json_parse(gad.kwargs); - gadget = self[gad.__class__](gad.back_id, args); - svguiWidgets[gadget.back_elt.id]=gadget; + gadget = new svguilib[gad.__class__](self, gad.id, args); + svguiWidgets[gadget.id]=gadget; //console.log('GADGET :' + gadget); } var elements = document.getElementsByTagName("svg"); @@ -67,5 +57,3 @@ //console.log("SVGUIWIDGETS : " + svguiWidgets); } ); - -Divmod.Base.addLoadEvent(init); \ No newline at end of file diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 plugins/python/modules/svgui/pous.xml --- a/plugins/python/modules/svgui/pous.xml Thu Aug 13 11:48:55 2009 +0200 +++ b/plugins/python/modules/svgui/pous.xml Fri Aug 14 16:26:19 2009 +0200 @@ -8,7 +8,7 @@ productVersion="0.0" creationDateTime="2008-12-14T16:53:26"/> + modificationDateTime="2009-08-12T15:35:33"> @@ -51,12 +51,12 @@ - + - - - + + + @@ -66,135 +66,59 @@ - + + + + + + - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -203,272 +127,33 @@ - - - - - - - - - - - 'int(SVGUI("SvguiButton","' - - - - - - - '",sele_id="' - - - - - - - '",state=' - - - - - - - ',toggle=True,active=True))' - - - - - - - BOOL#1 - - - + + + + + + + + + + + 'createSVGUIControl("textControl", back_id="' + + + back_id - - - - - - sele_id - - - - - - - set_state - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - current_state - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'SVGUI("SvguiTextCtrl","' - - - - - - - back_id - - - - - - - state - - - - - - - '",state="' - - + '")' - + @@ -487,7 +172,7 @@ - + @@ -506,23 +191,208 @@ - - + + + + + + BOOL#1 + + + - + - code + ID - - - - - - BOOL#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + set_text + + + + + + + 'setAttr(' + + + + + + + ',"text","' + + + + + + + '")' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text @@ -530,9 +400,9 @@ - - - + + + @@ -547,38 +417,68 @@ + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + - - + + - - + + @@ -586,10 +486,8 @@ - - - - + + @@ -608,69 +506,71 @@ - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - - - + + + + + + - - - - + + + + - + - - + + @@ -679,76 +579,165 @@ - - - - - - - - - - - 'int(SVGUI("SvguiButton","' + + + + + + + + + + + 'createSVGUIControl("button",back_id="' - + '",sele_id="' - - + + + + + + ',active=True)' + + + + + + + BOOL#1 + + + + + + + back_id + + + + + + + sele_id + + + + + + + set_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - '",state=' - - - - - - - ',active=True))' - - - - - - - BOOL#1 - - - - - - - back_id - - - - - - - sele_id - - - - - - - set_state - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -757,53 +746,286 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + state_in + + + - - + + - current_state + state_out - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + 'setAttr(' + + + + + + + ',"state",' + + + + + + + ')' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + 'int(getAttr(' + + + + + + + ',"state",False))' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '",toggle=' + + + - - - + + + @@ -817,11 +1039,25 @@ + + + + + + toggle + - + + + + + + + + @@ -833,21 +1069,24 @@ - - - + - + + + + + + - + @@ -856,200 +1095,328 @@ - - - - - - 'SVGUI("SvguiButton","' - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'createSVGUIControl("button",back_id="' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '",sele_id="' - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + '",toggle=True,active=False)' + + + + + + + BOOL#1 + + + back_id - - + + sele_id - - - - - - ',toggle=True)' - - - + + - '", state=' - - - - - - - state - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 'setAttr(' + + + + + + + ',"state",' + + + + + + + ')' + + + + + - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BOOL#1 - - - - - - - - - - - - - - - - - + + + + + + + + + + ID + + + + + + + + + + + + + + + + + state_in + diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 plugins/python/modules/svgui/svgui_server.py --- a/plugins/python/modules/svgui/svgui_server.py Thu Aug 13 11:48:55 2009 +0200 +++ b/plugins/python/modules/svgui/svgui_server.py Fri Aug 14 16:26:19 2009 +0200 @@ -8,77 +8,123 @@ svgfile = '%(svgfile)s' -svguiWidgets={} +svguiWidgets = {} + +currentId = 0 +def getNewId(): + global currentId + currentId += 1 + return currentId class SvguiWidget: - def __init__(self, classname, back_id, **kwargs): + def __init__(self, classname, id, **kwargs): self.classname = classname - self.back_id = back_id + self.id = id self.attrs = kwargs.copy() - self.lastattrs = kwargs.copy() + self.inputs = {} + self.outputs = {} self.inhibit = False self.changed = False - def setattr(self, attrname, value): - self.attrs[attrname] = value + def setinput(self, attrname, value): + self.inputs[attrname] = value - def getattr(self, attrname): - return self.args.get(attrname, None) + def getinput(self, attrname, default=None): + if not self.inputs.has_key(attrname): + self.inputs[attrname] = default + return self.inputs[attrname] - def update(self, **kwargs): + def setoutput(self, attrname, value): + if self.outputs.get(attrname) != value: + self.outputs[attrname] = value + self.changed = True + self.RefreshInterface() + + def updateoutputs(self, **kwargs): for attrname, value in kwargs.iteritems(): - if self.lastattrs.get(attrname, None) != value: + if self.outputs.get(attrname) != value: + self.outputs[attrname] = value self.changed = True - self.attrs[attrname] = value - self.lastattrs[attrname] = value + self.RefreshInterface() + + def RefreshInterface(self): interface = website.getHMI() - if interface is not None and self.changed and not self.inhibit: + if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: self.changed = False - interface.sendData(self) - - return self.attrs["state"] + d = interface.sendData(self) + if d is not None: + self.inhibit = True + d.addCallback(self.InterfaceRefreshed) + + def InterfaceRefreshed(self, result): + self.inhibit = False + if self.changed: + self.RefreshInterface() -def convert_to_builtin_type(obj): +def get_object_init_state(obj): # Convert objects to a dictionary of their representation - d = { '__class__':obj.classname, - 'back_id':obj.back_id, - 'kwargs':json.dumps(obj.attrs), + attrs = obj.attrs.copy() + attrs.update(obj.inputs) + d = { '__class__': obj.classname, + 'id': obj.id, + 'kwargs': json.dumps(attrs), } return d -def dataToSend(): - gadgets = [] - for gadget in svguiWidgets.values(): - gadgets.append(unicode(json.dumps(gadget, default=convert_to_builtin_type, indent=2), 'ascii')) - return gadgets +def get_object_current_state(obj): + # Convert objects to a dictionary of their representation + d = { '__class__': obj.classname, + 'id': obj.id, + 'kwargs': json.dumps(obj.outputs), + } + return d - -class SVGUI_HMI(athena.LiveElement): +class SVGUI_HMI(website.PLCHMI): jsClass = u"LiveSVGPage.LiveSVGWidget" docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), ]) + + def HMIinitialisation(self): + gadgets = [] + for gadget in svguiWidgets.values(): + gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) + d = self.callRemote('init', gadgets) + d.addCallback(self.HMIinitialised) + + def sendData(self,data): + if self.initialised: + return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) + return None + + def setattr(self, id, attrname, value): + svguiWidgets[id].setinput(attrname, value) - def sendData(self,data): - objDefer = self.callRemote('receiveData',unicode(json.dumps(data, default=convert_to_builtin_type, indent=2), 'ascii')) +def createSVGUIControl(*args, **kwargs): + id = getNewId() + gad = SvguiWidget(args[0], id, **kwargs) + svguiWidgets[id] = gad + gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] + interface = website.getHMI() + if isinstance(interface, SVGUI_HMI) and interface.initialised: + interface.callRemote('init', gadget) + return id - def initClient(self): - self.callRemote('init', dataToSend()) - - def setattr(self, id, attrname, value): - svguiWidgets[id].setattr(attrname, value) +def setAttr(id, attrname, value): + gad = svguiWidgets.get(id, None) + if gad is not None: + gad.setoutput(attrname, value) -def SVGUI(*args, **kwargs): - classname, back_id = args - gad = svguiWidgets.get(back_id, None) - if gad is None: - gad = SvguiWidget(classname, back_id, **kwargs) - svguiWidgets[back_id] = gad - gadget = [unicode(json.dumps(gad, default=convert_to_builtin_type, indent=2), 'ascii')] - interface = website.getHMI() - if interface is not None: - interface.callRemote('init', gadget) +def updateAttr(id, **kwargs): + gad = svguiWidgets.get(id, None) + if gad is not None: + gad.updateoutput(**kwargs) - return gad.update(**kwargs) +def getAttr(id, attrname, default=None): + gad = svguiWidgets.get(id, None) + if gad is not None: + return gad.getinput(attrname, default) + return default + diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 plugins/python/modules/svgui/svguilib.py --- a/plugins/python/modules/svgui/svguilib.py Thu Aug 13 11:48:55 2009 +0200 +++ b/plugins/python/modules/svgui/svguilib.py Fri Aug 14 16:26:19 2009 +0200 @@ -1,13 +1,14 @@ class button: - def __init__(self, parent, back_id, sele_id, toggle, state, active): + def __init__(self, parent, id, args): self.parent = parent - self.back_elt = getSVGElementById(back_id) - self.sele_elt = getSVGElementById(sele_id) - self.toggle = toggle - self.state = state - self.active = active + self.id = id + self.back_elt = getSVGElementById(args.back_id) + self.sele_elt = getSVGElementById(args.sele_id) + self.toggle = args.toggle + self.active = args.active + self.state = False self.dragging = False if toggle: self.up = not state @@ -40,9 +41,11 @@ self.sele_elt.setAttribute("visibility", "visible") self.back_elt.setAttribute("visibility", "hidden") - def updateState(self, value): - self.up = not value - self.updateElements() + def updateValues(self, values): + if values.state != self.state: + self.state = values.state + self.up = not self.state + self.updateElements() def handleEvent(self, evt): # Quand le bouton de la souris est presse @@ -57,7 +60,7 @@ else: self.up = False self.state = True - updateAttr(self.back_elt.id, 'state', self.state) + updateAttr(self.id, 'state', self.state) self.updateElements() if isCurrentObject(self) and self.dragging: @@ -76,31 +79,31 @@ evt.stopPropagation() if self.toggle and self.up == self.state: self.state = not self.state - updateAttr(self.back_elt.id, 'state', self.state) + updateAttr(self.id, 'state', self.state) elif not self.toggle: self.up = True self.state = False - updateAttr(self.back_elt.id, 'state', self.state) + updateAttr(self.id, 'state', self.state) self.updateElements() self.dragging = False class textControl: - def __init__(self, parent, back_id, state): + def __init__(self, parent, id, args): self.parent = parent - self.back_elt = getSVGElementById(back_id) - self.state = state - self.setValue(self.state) + self.id = id + self.back_elt = getSVGElementById(args.back_id) + self.value = "" + self.updateElements() + + def updateValues(self, values): + if values.text != self.value: + self.value = values.text + self.updateElements() + + def updateElements(self): + self.back_elt.firstChild.firstChild.textContent = self.value def handleEvent(self, evt): pass - - def getValue(self): - return self.back_elt.firstChild.firstChild.textContent - - def setValue(self, value): - self.back_elt.firstChild.firstChild.textContent = value - - def updateState(self, value): - self.setValue(value) \ No newline at end of file diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 tests/linux/test_svgui/plc.xml --- a/tests/linux/test_svgui/plc.xml Thu Aug 13 11:48:55 2009 +0200 +++ b/tests/linux/test_svgui/plc.xml Fri Aug 14 16:26:19 2009 +0200 @@ -8,7 +8,7 @@ productVersion="0.0" creationDateTime="2008-12-14T16:21:19"/> + modificationDateTime="2009-08-14T16:13:40"> @@ -73,100 +73,96 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - - - - - - + + + + - - - - + + + + - + - - - - - - + + + + + + @@ -175,25 +171,23 @@ - + - + - + - - - - + + @@ -201,158 +195,49 @@ counter - - - - - - INT#1 + + + + + + BOOL#1 - + 'stop_back' - + 'stop_sele' - + 'text_compteur' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 'led_stop' - + 'led_start' - + @@ -373,15 +258,25 @@ + + + + + - - - - - - - + + + + + + + + + + + + @@ -402,408 +297,444 @@ 'btn1_sele' - - + + - + - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - - - + + - + - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + - + 'btn2_back' - + 'btn3_sele' - + 'btn3_back' - + 'btn2_sele' - + 'btn4_back' - + 'btn4_sele' - + 'btn5_back' - + 'btn5_sele' - + 'btn6_back' - + 'btn6_sele' - + 'btn7_back' - + 'btn7_sele' - + 'btn8_back' - + 'btn8_sele' - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + + + + + + + + + + - + @@ -812,7 +743,7 @@ - + @@ -820,82 +751,353 @@ DigitalBit0 - + - - - + + + DigitalBit1 - + - - - + + + DigitalBit7 - + - - - + + + DigitalBit6 - + - - - + + + DigitalBit5 - + - - - + + + DigitalBit4 - + - - - + + + DigitalBit3 - + - - - + + + DigitalBit2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BOOL#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BOOL#1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + counter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 46d7d2ce84d2 -r 5c0f34a9ab00 webinterface.js --- a/webinterface.js Thu Aug 13 11:48:55 2009 +0200 +++ b/webinterface.js Fri Aug 14 16:26:19 2009 +0200 @@ -1,5 +1,9 @@ // import Nevow.Athena +function init() { + Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'HMIinitialisation'); +} + WebInterface.PLC = Nevow.Athena.Widget.subclass('WebInterface.PLC'); WebInterface.PLC.method( 'updateHMI', @@ -12,6 +16,9 @@ function childAdded(widget) { var node = self.nodeById('content'); node.replaceChild(widget.node, node.getElementsByTagName('div')[0]); + init(); }); }); - }); \ No newline at end of file + }); + +Divmod.Base.addLoadEvent(init); \ No newline at end of file