6 from nevow import rend, appserver, inevow, tags, loaders, athena |
6 from nevow import rend, appserver, inevow, tags, loaders, athena |
7 import simplejson as json |
7 import simplejson as json |
8 |
8 |
9 svgfile = '%(svgfile)s' |
9 svgfile = '%(svgfile)s' |
10 |
10 |
11 svguiWidgets={} |
11 svguiWidgets = {} |
|
12 |
|
13 currentId = 0 |
|
14 def getNewId(): |
|
15 global currentId |
|
16 currentId += 1 |
|
17 return currentId |
12 |
18 |
13 class SvguiWidget: |
19 class SvguiWidget: |
14 |
20 |
15 def __init__(self, classname, back_id, **kwargs): |
21 def __init__(self, classname, id, **kwargs): |
16 self.classname = classname |
22 self.classname = classname |
17 self.back_id = back_id |
23 self.id = id |
18 self.attrs = kwargs.copy() |
24 self.attrs = kwargs.copy() |
19 self.lastattrs = kwargs.copy() |
25 self.inputs = {} |
|
26 self.outputs = {} |
20 self.inhibit = False |
27 self.inhibit = False |
21 self.changed = False |
28 self.changed = False |
22 |
29 |
23 def setattr(self, attrname, value): |
30 def setinput(self, attrname, value): |
24 self.attrs[attrname] = value |
31 self.inputs[attrname] = value |
25 |
32 |
26 def getattr(self, attrname): |
33 def getinput(self, attrname, default=None): |
27 return self.args.get(attrname, None) |
34 if not self.inputs.has_key(attrname): |
|
35 self.inputs[attrname] = default |
|
36 return self.inputs[attrname] |
28 |
37 |
29 def update(self, **kwargs): |
38 def setoutput(self, attrname, value): |
|
39 if self.outputs.get(attrname) != value: |
|
40 self.outputs[attrname] = value |
|
41 self.changed = True |
|
42 self.RefreshInterface() |
|
43 |
|
44 def updateoutputs(self, **kwargs): |
30 for attrname, value in kwargs.iteritems(): |
45 for attrname, value in kwargs.iteritems(): |
31 if self.lastattrs.get(attrname, None) != value: |
46 if self.outputs.get(attrname) != value: |
|
47 self.outputs[attrname] = value |
32 self.changed = True |
48 self.changed = True |
33 self.attrs[attrname] = value |
49 self.RefreshInterface() |
34 self.lastattrs[attrname] = value |
50 |
|
51 def RefreshInterface(self): |
35 interface = website.getHMI() |
52 interface = website.getHMI() |
36 if interface is not None and self.changed and not self.inhibit: |
53 if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: |
37 self.changed = False |
54 self.changed = False |
38 interface.sendData(self) |
55 d = interface.sendData(self) |
39 |
56 if d is not None: |
40 return self.attrs["state"] |
57 self.inhibit = True |
|
58 d.addCallback(self.InterfaceRefreshed) |
|
59 |
|
60 def InterfaceRefreshed(self, result): |
|
61 self.inhibit = False |
|
62 if self.changed: |
|
63 self.RefreshInterface() |
41 |
64 |
42 def convert_to_builtin_type(obj): |
65 def get_object_init_state(obj): |
43 # Convert objects to a dictionary of their representation |
66 # Convert objects to a dictionary of their representation |
44 d = { '__class__':obj.classname, |
67 attrs = obj.attrs.copy() |
45 'back_id':obj.back_id, |
68 attrs.update(obj.inputs) |
46 'kwargs':json.dumps(obj.attrs), |
69 d = { '__class__': obj.classname, |
|
70 'id': obj.id, |
|
71 'kwargs': json.dumps(attrs), |
47 } |
72 } |
48 return d |
73 return d |
49 |
74 |
50 def dataToSend(): |
75 def get_object_current_state(obj): |
51 gadgets = [] |
76 # Convert objects to a dictionary of their representation |
52 for gadget in svguiWidgets.values(): |
77 d = { '__class__': obj.classname, |
53 gadgets.append(unicode(json.dumps(gadget, default=convert_to_builtin_type, indent=2), 'ascii')) |
78 'id': obj.id, |
54 return gadgets |
79 'kwargs': json.dumps(obj.outputs), |
|
80 } |
|
81 return d |
55 |
82 |
56 |
83 class SVGUI_HMI(website.PLCHMI): |
57 class SVGUI_HMI(athena.LiveElement): |
|
58 jsClass = u"LiveSVGPage.LiveSVGWidget" |
84 jsClass = u"LiveSVGPage.LiveSVGWidget" |
59 |
85 |
60 docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ |
86 docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ |
61 tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), |
87 tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), |
62 ]) |
88 ]) |
|
89 |
|
90 def HMIinitialisation(self): |
|
91 gadgets = [] |
|
92 for gadget in svguiWidgets.values(): |
|
93 gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) |
|
94 d = self.callRemote('init', gadgets) |
|
95 d.addCallback(self.HMIinitialised) |
|
96 |
|
97 def sendData(self,data): |
|
98 if self.initialised: |
|
99 return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) |
|
100 return None |
|
101 |
|
102 def setattr(self, id, attrname, value): |
|
103 svguiWidgets[id].setinput(attrname, value) |
63 |
104 |
64 def sendData(self,data): |
105 def createSVGUIControl(*args, **kwargs): |
65 objDefer = self.callRemote('receiveData',unicode(json.dumps(data, default=convert_to_builtin_type, indent=2), 'ascii')) |
106 id = getNewId() |
|
107 gad = SvguiWidget(args[0], id, **kwargs) |
|
108 svguiWidgets[id] = gad |
|
109 gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] |
|
110 interface = website.getHMI() |
|
111 if isinstance(interface, SVGUI_HMI) and interface.initialised: |
|
112 interface.callRemote('init', gadget) |
|
113 return id |
66 |
114 |
67 def initClient(self): |
115 def setAttr(id, attrname, value): |
68 self.callRemote('init', dataToSend()) |
116 gad = svguiWidgets.get(id, None) |
69 |
117 if gad is not None: |
70 def setattr(self, id, attrname, value): |
118 gad.setoutput(attrname, value) |
71 svguiWidgets[id].setattr(attrname, value) |
|
72 |
119 |
73 def SVGUI(*args, **kwargs): |
120 def updateAttr(id, **kwargs): |
74 classname, back_id = args |
121 gad = svguiWidgets.get(id, None) |
75 gad = svguiWidgets.get(back_id, None) |
122 if gad is not None: |
76 if gad is None: |
123 gad.updateoutput(**kwargs) |
77 gad = SvguiWidget(classname, back_id, **kwargs) |
|
78 svguiWidgets[back_id] = gad |
|
79 gadget = [unicode(json.dumps(gad, default=convert_to_builtin_type, indent=2), 'ascii')] |
|
80 interface = website.getHMI() |
|
81 if interface is not None: |
|
82 interface.callRemote('init', gadget) |
|
83 |
124 |
84 return gad.update(**kwargs) |
125 def getAttr(id, attrname, default=None): |
|
126 gad = svguiWidgets.get(id, None) |
|
127 if gad is not None: |
|
128 return gad.getinput(attrname, default) |
|
129 return default |
|
130 |