Revisão | 6dc5985e8a75b4dc7d3977c7e722dc3a188aadbb (tree) |
---|---|
Hora | 2013-03-04 01:50:45 |
Autor | bijoux |
Commiter | bijoux |
new dynamic port arrangement
@@ -1,7 +1,5 @@ | ||
1 | 1 | # coding: utf-8 |
2 | 2 | |
3 | -#TODO: タプルパラメータパネルの追加 | |
4 | -#TODO: 動的なターミナル表示とリンクの修正 | |
5 | 3 | #TODO: キャンバスウィジェット |
6 | 4 | #TODO: マップの保存とリストア |
7 | 5 | #TODO: パラメータの保存 |
@@ -64,10 +62,11 @@ | ||
64 | 62 | laf.link(laf.port(rt.children['renderer'],'vtkobj'),laf.port(w,'renderer')) |
65 | 63 | # |
66 | 64 | #FIXME: タプルブリッジの試験用 |
67 | - # laf.port(rt.children['actor1'],'vtkobj').unlink() | |
68 | - # o = laf.data.TupleBridge() | |
69 | - # laf.link(laf.port(rt.children['spheresource'],'center'),laf.port(o,'value')) | |
70 | - # del o | |
65 | + laf.port(rt.children['actor1'],'vtkobj').unlink() | |
66 | + o = laf.data.TupleBridge() | |
67 | + laf.link(laf.port(rt.children['spheresource'],'center'),laf.port(o,'value')) | |
68 | + del o | |
69 | + # -- | |
71 | 70 | # |
72 | 71 | Tkinter.mainloop() |
73 | 72 | |
\ No newline at end of file |
@@ -226,9 +226,9 @@ | ||
226 | 226 | del canvas._location_buffer[logic] |
227 | 227 | CanvasItem.__init__(self,canvas,tag,loc) |
228 | 228 | self._logic = weakref.ref(logic) |
229 | - self.myports = laf.WeakValueList() | |
229 | + self.myports = weakref.WeakValueDictionary() | |
230 | 230 | self.draw(self.shape) |
231 | - self.generate_myports() | |
231 | + #self.generate_myports() | |
232 | 232 | self.bind('<Button1-Motion>',self.leftdrag) |
233 | 233 | self.bind('<Button1-ButtonRelease>',self.leftrelease) |
234 | 234 | self.bind('<Double-Button-1>',self.popup_equipment) |
@@ -250,6 +250,8 @@ | ||
250 | 250 | def check_model(self,e): # <<CheckModel>> |
251 | 251 | if not self.logic: |
252 | 252 | self.destroy() |
253 | + return | |
254 | + self.populate_ports() | |
253 | 255 | def leftdrag(self,e): |
254 | 256 | try: |
255 | 257 | self._start |
@@ -263,7 +265,7 @@ | ||
263 | 265 | self._start = [e.x,e.y] |
264 | 266 | self.move(dx,dy) |
265 | 267 | # 配下のポートも同時に動かす |
266 | - for item in self.myports.tolist(): | |
268 | + for item in [v for v in self.myports.itervalues()]: | |
267 | 269 | item.move(dx,dy) |
268 | 270 | def leftrelease(self,e): |
269 | 271 | try: |
@@ -272,30 +274,92 @@ | ||
272 | 274 | return |
273 | 275 | if self._start is not None: |
274 | 276 | self._start = None |
275 | - def generate_myports(self): | |
276 | - # ポートアイテムを生成する | |
277 | + def populate_ports(self): | |
278 | + # ポートアイテムを居住させる | |
279 | + # 現在、ロジックが保持しているが未居住の実ポートを居住させる | |
280 | + # すでに居住しているが、ロジックから廃棄されたポートアイテムを退去させる | |
277 | 281 | def generate(ports,xoffset=0,yoffset=0,direction=Tkinter.LEFT): |
278 | - yoffset = -16 * (len(ports) - 1) / 2 | |
282 | + # ポートを生成する | |
283 | + # 生成したポートは self.myports に格納する | |
284 | + #FIXME: 単純化のために最初のポートの位置を中心に合わせたのを直しておくように | |
285 | + #yoffset = -16 * (len(ports) - 1) / 2 | |
286 | + yoffset = 0 | |
287 | + # | |
279 | 288 | keys = ports.keys() |
280 | 289 | keys.sort() # ターミナルの配置を英数降順で |
281 | 290 | for key in keys: |
282 | - actprt = ports[key].actualport(self.logic) | |
291 | + actprt = ports[key] | |
283 | 292 | myport = CanvasPort(self.canvas,actprt,direction=direction,tag=self.tag,loc=(x+xoffset,y+yoffset),name=key) |
284 | - #FIXME: remove this line | |
285 | - # self.canvas.following_terminals[attr] = weakref.ref(myport) | |
286 | - self.myports.append(myport) | |
293 | + self.myports[key] = myport | |
287 | 294 | yoffset += 16 |
288 | 295 | x,y = self.loc |
289 | 296 | lports,rports = {},{} |
290 | - #FIXME: current status | |
291 | - for name,port in laf.getproxports(self.logic).iteritems(): | |
297 | + #FIXME: ユーザが任意に左右を振り分けられるようにする | |
298 | + myports = [o.substance for o in self.myports.itervalues()] # すでに居住している実ポートのリストを収集する | |
299 | + for name,port in laf.getports(self.logic).iteritems(): | |
300 | + if port in myports: | |
301 | + # すでに居住しているポートであればなにもしない | |
302 | + continue | |
292 | 303 | # 右に表示するか左に表示するか振り分け |
293 | - if isinstance(port,laf.Rule): | |
304 | + if isinstance(port,laf.ActualRule): | |
294 | 305 | rports[name] = port |
295 | 306 | else: |
296 | 307 | lports[name] = port |
308 | + # ポートアイテムを生成する | |
297 | 309 | generate(lports,-50,direction=Tkinter.LEFT) |
298 | 310 | generate(rports,50,direction=Tkinter.RIGHT) |
311 | + # ポートアイテムの表示位置を調整する | |
312 | + # 左右配置されているポートアイテムを収集する | |
313 | + lpis,rpis = {},{} | |
314 | + for key,item in self.myports.iteritems(): | |
315 | + if item.loc[0] < x: | |
316 | + lpis[key] = item | |
317 | + else: | |
318 | + rpis[key] = item | |
319 | + # 左配置されているポートの位置を計算する | |
320 | + yoffset = -16 * (len(lpis) - 1) / 2 | |
321 | + keys = lpis.keys() | |
322 | + keys.sort() # ターミナルの配置を英数降順で | |
323 | + for key in keys: | |
324 | + o = lpis[key] | |
325 | + px,py = o.loc | |
326 | + o.move(0,y+yoffset-py) | |
327 | + yoffset +=16 | |
328 | + # 右は位置されているポートの位置を計算する | |
329 | + yoffset = -16 * (len(rpis) - 1) / 2 | |
330 | + keys = rpis.keys() | |
331 | + keys.sort() # ターミナルの配置を英数降順で | |
332 | + for key in keys: | |
333 | + o = rpis[key] | |
334 | + px,py = o.loc | |
335 | + o.move(0,y+yoffset-py) | |
336 | + yoffset +=16 | |
337 | +# | |
338 | + | |
339 | +# def generate_myports(self): | |
340 | +# # ポートアイテムを生成する | |
341 | +# def generate(ports,xoffset=0,yoffset=0,direction=Tkinter.LEFT): | |
342 | +# yoffset = -16 * (len(ports) - 1) / 2 | |
343 | +# keys = ports.keys() | |
344 | +# keys.sort() # ターミナルの配置を英数降順で | |
345 | +# for key in keys: | |
346 | +# actprt = ports[key].actualport(self.logic) | |
347 | +# myport = CanvasPort(self.canvas,actprt,direction=direction,tag=self.tag,loc=(x+xoffset,y+yoffset),name=key) | |
348 | +# #FIXME: remove this line | |
349 | +# # self.canvas.following_terminals[attr] = weakref.ref(myport) | |
350 | +# self.myports.append(myport) | |
351 | +# yoffset += 16 | |
352 | +# x,y = self.loc | |
353 | +# lports,rports = {},{} | |
354 | +# #FIXME: current status | |
355 | +# for name,port in laf.getproxports(self.logic).iteritems(): | |
356 | +# # 右に表示するか左に表示するか振り分け | |
357 | +# if isinstance(port,laf.Rule): | |
358 | +# rports[name] = port | |
359 | +# else: | |
360 | +# lports[name] = port | |
361 | +# generate(lports,-50,direction=Tkinter.LEFT) | |
362 | +# generate(rports,50,direction=Tkinter.RIGHT) | |
299 | 363 | def popup_equipment(self,e): # for Tk Event |
300 | 364 | logic = self.logic |
301 | 365 | module = inspect.getmodule(logic) |
@@ -719,13 +783,15 @@ | ||
719 | 783 | (.5*(self.sx+self.ex),self.ey), |
720 | 784 | (self.ex,self.ey)),{'width':1,'smooth':True,'splinesteps':10})] |
721 | 785 | def check_model(self,e): |
722 | - ''' | |
723 | - 追跡しているノードが削除されるかノードとポートが監視するコンテナが異なっていれば自身を削除する | |
724 | - ''' | |
725 | 786 | # -- |
726 | - # 追跡していたノードアイテムが削除されるか、 | |
727 | - # たらゴミ箱に入る | |
787 | + # 追跡していたポートアイテムが削除されてしまったか、 | |
788 | + # ノードが削除されるか、ノードとポートが監視するコンテナが異なっていればゴミ箱に入る | |
728 | 789 | # -- |
790 | + try: | |
791 | + self.portitem.substance | |
792 | + except AttributeError: | |
793 | + self.canvas.scrap.append(self) | |
794 | + return | |
729 | 795 | if self.nodeitem == None or not self.portitem.substance.container == self.nodeitem.substance: |
730 | 796 | self.canvas.scrap.append(self) |
731 | 797 | return |
@@ -1,25 +1,9 @@ | ||
1 | 1 | # coding: utf-8 |
2 | 2 | |
3 | -from ingredient import Logic,ActualEvent,event,getports,port | |
4 | - | |
5 | -#class SpecificTuple(tuple,object): | |
6 | -# keys = None | |
7 | -# def __new__(self,*args): | |
8 | -# if len(args) == 1 and isinstance(args[0],tuple): | |
9 | -# return tuple(args[0]) | |
10 | -# else: | |
11 | -# return tuple(args) | |
12 | -# def __init__(self,*args): | |
13 | -# tuple.__init__(self,args) | |
3 | +from ingredient import Logic,ActualEvent,event | |
14 | 4 | |
15 | 5 | class SpecificTuple(tuple,object): |
16 | 6 | keys = None |
17 | -#FIXME: 以下のコードだとタプルが返されてしまうので注意! | |
18 | -# def __new__(self,*args): | |
19 | -# if len(args) == 1 and isinstance(args[0],tuple): | |
20 | -# return tuple(args[0]) | |
21 | -# else: | |
22 | -# return tuple(args) | |
23 | 7 | |
24 | 8 | class Point(SpecificTuple): |
25 | 9 | keys = ('x','y','z') |
@@ -39,7 +23,7 @@ | ||
39 | 23 | value = self.value |
40 | 24 | self._block = None |
41 | 25 | for i,k in enumerate(self.keys): |
42 | - getattr(self,k).set(self.value[i]) | |
26 | + getattr(self,k).set(value[i]) | |
43 | 27 | del self._block |
44 | 28 | def _link_value(self): |
45 | 29 | self.keys = self.value.keys |
@@ -51,36 +35,8 @@ | ||
51 | 35 | def _unlink_value(self): |
52 | 36 | for k in self.keys: |
53 | 37 | delattr(self,k) |
54 | - self.keys = None | |
38 | + # value をクリアする | |
39 | + self.keys = () # value をクリアする際に keys のイテレータが要求されるので | |
55 | 40 | self.value = None |
56 | - | |
57 | -#class SpecificData(object): pass | |
58 | -# | |
59 | -#class Point(SpecificData): | |
60 | -# keys = ('x','y','z') | |
61 | -# #FIXME: 相互同期メカニズム | |
62 | -# def __init__(self,x=0,y=0,z=0): | |
63 | -# self.x = x | |
64 | -# self.y = y | |
65 | -# self.z = z | |
66 | -# @event | |
67 | -# def data(self): | |
68 | -# self._block = None | |
69 | -# self.x = self.data[0] | |
70 | -# self.y = self.data[1] | |
71 | -# self.z = self.data[2] | |
72 | -# del self._block | |
73 | -# @event | |
74 | -# def x(self): self.update() | |
75 | -# @event | |
76 | -# def y(self): self.update() | |
77 | -# @event | |
78 | -# def z(self): self.update() | |
79 | -# def update(self): | |
80 | -# try: | |
81 | -# self._block | |
82 | -# except: | |
83 | -# self.data = (self.x,self.y,self.z) | |
84 | - | |
85 | -#class PositionWidget: | |
86 | - | |
41 | + # keys をクリアする | |
42 | + self.keys = None |
@@ -10,8 +10,8 @@ | ||
10 | 10 | Logic.__init__(self,*args,**kw) |
11 | 11 | self._vtkobj = self.vtkClass() |
12 | 12 | self.initialize() |
13 | - # FIXME:これを実行しないとルールが生成されないのでリンク時にエラーとなることがある?うそ? | |
14 | - # self.vtkobj | |
13 | + # これを実行しないと実ポートが生成されないのでマップへのオブジェクト追加時にリンク前に実ポートが生成されないことがある | |
14 | + self.vtkobj | |
15 | 15 | def initialize(self): pass |
16 | 16 | @rule |
17 | 17 | def vtkobj(self): return self._vtkobj |