Commit MetaInfo

Revisión4a966ff0d08f9003f54fa8bcf85bd7f2f54ebf03 (tree)
Tiempo2013-03-03 19:25:24
Autorbijoux
Commiterbijoux

Log Message

change behavior of getports

Cambiar Resumen

Diferencia incremental

diff -r b75ed0ad4d5f -r 4a966ff0d08f src/pylafiii/__init__.py
--- a/src/pylafiii/__init__.py Fri Mar 01 15:19:31 2013 +0900
+++ b/src/pylafiii/__init__.py Sun Mar 03 19:25:24 2013 +0900
@@ -1,4 +1,5 @@
11 from ingredient import *
22 from chef import Recipe
33 import chef
4+import data
45 import vtkext
diff -r b75ed0ad4d5f -r 4a966ff0d08f src/pylafiii/chef.py
--- a/src/pylafiii/chef.py Fri Mar 01 15:19:31 2013 +0900
+++ b/src/pylafiii/chef.py Sun Mar 03 19:25:24 2013 +0900
@@ -4,6 +4,7 @@
44 import time
55 import threading
66 import inspect
7+import types
78 import imp
89 import uuid
910 import random
@@ -13,8 +14,24 @@
1314 import Tkinter
1415 import ttk
1516 import ingredient as laf
17+import data
1618 from ingredient import rule,event,Logic,Port
1719
20+def editable(logic):
21+ '''
22+ コントロールパネルで自動生成可能なポートを返す
23+ '''
24+ MYTYPES = (types.IntType,types.FloatType,types.StringType,
25+ numpy.float64,numpy.int64,data.SpecificData)
26+ members = {}
27+ for k,v in laf.getproxports(logic).iteritems():
28+ value = v.actualport(logic).container.value
29+ for t in MYTYPES:
30+ if isinstance(value,t):
31+ members[k] = v
32+ break
33+ return members
34+
1835 def getClass(domelement):
1936 module_name = domelement.getAttribute('module')
2037 cls_name = domelement.getAttribute('cls')
@@ -214,6 +231,7 @@
214231 self.generate_myports()
215232 self.bind('<Button1-Motion>',self.leftdrag)
216233 self.bind('<Button1-ButtonRelease>',self.leftrelease)
234+ self.bind('<Double-Button-1>',self.popup_equipment)
217235 self.bind('<Button-2>',lambda e:self.canvas.rmenu.queue((self.Menu,self,e)))
218236 self.event.bind('<<CheckModel>>',self.check_model)
219237 @property
@@ -270,7 +288,7 @@
270288 x,y = self.loc
271289 lports,rports = {},{}
272290 #FIXME: current status
273- for name,port in laf.getports(self.logic).iteritems():
291+ for name,port in laf.getproxports(self.logic).iteritems():
274292 # 右に表示するか左に表示するか振り分け
275293 if isinstance(port,laf.Rule):
276294 rports[name] = port
@@ -278,7 +296,128 @@
278296 lports[name] = port
279297 generate(lports,-50,direction=Tkinter.LEFT)
280298 generate(rports,50,direction=Tkinter.RIGHT)
299+ def popup_equipment(self,e): # for Tk Event
300+ logic = self.logic
301+ module = inspect.getmodule(logic)
302+# recipes = []
303+# for k,v in sys.modules[module.__name__].__dict__.iteritems():
304+# if inspect.isclass(v):
305+# for cls in inspect.getmro(v):
306+# if cls == Recipe:
307+# if not v.RECIPIENT == None:
308+# if isinstance(self.logic,v.RECIPIENT):
309+# recipes.append(v)
310+# break
311+# chef = self.canvas.chef
312+# if recipes:
313+# recipe = recipes[0]()
314+# w = chef.cook(recipe,Tkinter.Toplevel(chef))
315+# w.connect(self.logic)
316+# w.pack()
317+# else:
318+# if editable(self.logic):
319+# ControlPanel(Tkinter.Toplevel(chef),logic=self.logic).pack()
320+ if editable(logic):
321+ ControlPanel(Tkinter.Toplevel(self.canvas),logic=logic).pack()
281322
323+class ControlPanel(Tkinter.Frame,object):
324+ def __init__(self,*args,**kw):
325+ if kw.has_key('logic'):
326+ logic = kw['logic']
327+ del kw['logic']
328+ Tkinter.Frame.__init__(self,*args,**kw)
329+ members = editable(logic)
330+ keys = members.keys()
331+ keys.sort()
332+ i = 0
333+ for k in keys:
334+ v = members[k]
335+ value = getattr(logic,k)
336+ if isinstance(value,data.SpecificData):
337+ #TODO: より汎用性のある方式へ変更しなければいけない
338+ o = SmartPanel(self,logic,k); o.grid(column=0,row=i,columnspan=2)
339+ p = ControlPanel(o,logic=value); p.pack()
340+ laf.link(laf.port(value,'data'),laf.port(o,'receiver'))
341+ else:
342+ l = Tkinter.Label(self,text=k); l.grid(column=0,row=i)
343+ e = Entry(self); e.grid(column=1,row=i)
344+ setattr(e,'value',value)
345+ laf.link(laf.port(logic,k),laf.port(e,'value'))
346+ i += 1
347+
348+#TODO: 結構トリッキーなのでドキュメントにしておくこと
349+#FIXME: 縁ありフレームにする
350+class SmartPanel(Tkinter.LabelFrame,object):
351+ # データクラスの変更を補足してデータ更新を促すクラス
352+ @event
353+ def receiver(self):
354+ setattr(self.logic,self.portid,getattr(self.logic,self.portid))
355+ def __init__(self,master=None,logic=None,portid=None,*args,**kw):
356+ Tkinter.LabelFrame.__init__(self,master,text=portid,*args,**kw)
357+ self._logic = weakref.ref(logic)
358+ self.portid = portid
359+ @property
360+ def logic(self):
361+ return self._logic()
362+##FIXME: 適切な名前へ!
363+#class SmartControlPanel(Tkinter.Frame,object):
364+# # データクラスの変更を捕捉する機能を有するパネル
365+# @event
366+# def receiver(self):
367+# self.updated()
368+# def updated(self):
369+# setattr(self.logic,self.name,getattr(self.logic,self.name))
370+# def __init__(self,*args,**kw):
371+# if kw.has_key('logic'):
372+# logic = kw['logic']
373+# del kw['logic']
374+# Tkinter.Frame.__init__(self,*args,**kw)
375+# self.logic = weakref.ref(logic)
376+# self.name
377+# members = editable(logic)
378+# i = 0
379+# for k,v in members.iteritems():
380+# value = getattr(logic,k)
381+# if isinstance(value,data.SpecificData):
382+# #TODO: より汎用性のある方式へ変更しなければいけない
383+# p = SmartControlPanel(self,logic=value); p.grid(column=0,row=i,columnspan=2)
384+# else:
385+# l = Tkinter.Label(self,text=k); l.grid(column=0,row=i)
386+# e = Entry(self); e.grid(column=1,row=i)
387+# setattr(e,'value',value)
388+# laf.link(laf.port(logic,k),laf.port(e,'value'))
389+# i += 1
390+
391+
392+class Entry(Tkinter.Entry,object):
393+ def __init__(self,master=None,format='%s',cnf={},**kw):
394+ Tkinter.Entry.__init__(self,master,cnf,**kw)
395+ self.format = format
396+ self._buffer = None
397+ self._updated = False
398+ self._callback_id = self.bind('<Return>',self._backward) # RETURNキーが押されたら値を確定する
399+ self._idle_loop()
400+ def _idle_loop(self):
401+ if self._updated:
402+ self._forward(self._buffer)
403+ self._updated = False
404+ self.after(50,self._idle_loop)
405+ @event
406+ def value(self):
407+ self._buffer = self.value
408+ self._updated = True
409+ def _forward(self,value):
410+ self.delete(0,len(self.get()))
411+ self.insert(0,self.format % value)
412+ def _backward(self,*args):
413+ container = laf.port(self,'value').container
414+ try:
415+ self.value = type(container.value)(self.get())
416+ except ValueError:
417+ self._buffer = container.value
418+ self._updated = True
419+
420+#FIXME:
282421 class StayEventDispatcher:
283422 def __init__(self,obj):
284423 self.isstayed = False
diff -r b75ed0ad4d5f -r 4a966ff0d08f src/pylafiii/data.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pylafiii/data.py Sun Mar 03 19:25:24 2013 +0900
@@ -0,0 +1,33 @@
1+# coding: utf-8
2+
3+from ingredient import event
4+
5+class SpecificData(object): pass
6+
7+class Point(SpecificData):
8+ #FIXME: 相互同期メカニズム
9+ def __init__(self,x=0,y=0,z=0):
10+ self.x = x
11+ self.y = y
12+ self.z = z
13+ @event
14+ def data(self):
15+ self._block = None
16+ self.x = self.data[0]
17+ self.y = self.data[1]
18+ self.z = self.data[2]
19+ del self._block
20+ @event
21+ def x(self): self.update()
22+ @event
23+ def y(self): self.update()
24+ @event
25+ def z(self): self.update()
26+ def update(self):
27+ try:
28+ self._block
29+ except:
30+ self.data = (self.x,self.y,self.z)
31+
32+#class PositionWidget:
33+
diff -r b75ed0ad4d5f -r 4a966ff0d08f src/pylafiii/ingredient.py
--- a/src/pylafiii/ingredient.py Fri Mar 01 15:19:31 2013 +0900
+++ b/src/pylafiii/ingredient.py Sun Mar 03 19:25:24 2013 +0900
@@ -8,7 +8,7 @@
88
99 actualports = weakref.WeakKeyDictionary()
1010
11-def getports(owner):
11+def getproxports(owner):
1212 '''オーナが保持するすべてのポートリストを取得する'''
1313 if inspect.isclass(owner):
1414 klass = owner
@@ -22,6 +22,8 @@
2222 if not k in result: result[k] = v
2323 return result
2424
25+
26+
2527 class Singleton(type):
2628 # http://code.activestate.com/recipes/412551/
2729 def __init__(self,*args):
@@ -196,7 +198,7 @@
196198 self.sources
197199 except AttributeError:
198200 self.sources = self.proxy.sources
199- ports = getports(self.owner)
201+ ports = getproxports(self.owner)
200202 # check update requirements
201203 for name in self.sources:
202204 if self not in ports[name].actualport(self.owner).container.hootprint:
@@ -231,7 +233,7 @@
231233 '''オーナーインスタンスからの参照名を取得する'''
232234 if self._name == None: # オーナーインスタンスが生成されてから最初に参照されたときには名称探索をする
233235 # 呼び出しのコンテキストから、オーナーインスタンスにオブジェクトが存在することが保証されているので(はずなので)チェック省略
234- for name, v in getports(owner).iteritems(): # オーナークラスのメンバ全体について
236+ for name, v in getproxports(owner).iteritems(): # オーナークラスのメンバ全体について
235237 if v == self:
236238 self._name = name # 自身と一致するインスタンスの名称をセットする
237239 # まだオーナーに実体が生成されていなければすべての実体を生成する
@@ -240,7 +242,7 @@
240242 return self._name
241243 def newactualports(self,owner):
242244 '''オーナーに属するすべてのターミナルの属性を生成する'''
243- ports = getports(owner)
245+ ports = getproxports(owner)
244246 for name, port in ports.iteritems():
245247 owner.__dict__[name] = port.ActualPort(owner,port,port.initvalue)
246248
@@ -266,7 +268,7 @@
266268 class PortGen(type):
267269 def __new__(cls,cls_name,bases,attrs):
268270 klass = type.__new__(cls,cls_name,bases,attrs)
269- ports = getports(klass)
271+ ports = getproxports(klass)
270272 for k,v in ports.iteritems():
271273 if not isinstance(v,Rule):
272274 continue
@@ -361,7 +363,7 @@
361363
362364 def port(owner,name):
363365 '''オーナが保持するポートの実体を取得する'''
364- ports = getports(owner)
366+ ports = getproxports(owner)
365367 if name in ports:
366368 return ports[name].actualport(owner)
367369 else:
diff -r b75ed0ad4d5f -r 4a966ff0d08f src/pylafiii/vtkext/source.py
--- a/src/pylafiii/vtkext/source.py Fri Mar 01 15:19:31 2013 +0900
+++ b/src/pylafiii/vtkext/source.py Sun Mar 03 19:25:24 2013 +0900
@@ -2,6 +2,7 @@
22
33 import vtk
44 from pylafiii.ingredient import Logic,Port,rule,event
5+from pylafiii.data import Point
56 from base import vtkLogic
67
78 class SphereSource(vtkLogic):
@@ -9,3 +10,13 @@
910 output = Port()
1011 def initialize(self):
1112 self.output = self.vtkobj.GetOutput()
13+ #FIXME: Pointが更新されたことを知る仕組みが必要!
14+ self.center = Point(*self.vtkobj.GetCenter())
15+ self.radius = self.vtkobj.GetRadius()
16+ @event
17+ def center(self):
18+ self.vtkobj.SetCenter(*self.center.data)
19+ @event
20+ def radius(self):
21+ self.vtkobj.SetRadius(self.radius)
22+
\ No newline at end of file
Show on old repository browser