Revisão | 4dca62c9714a33d00d977e9a6757bc1711cf4805 (tree) |
---|---|
Hora | 2013-03-20 17:34:33 |
Autor | bijoux |
Commiter | bijoux |
New RubberString
@@ -20,9 +20,18 @@ | ||
20 | 20 | import tkFileDialog |
21 | 21 | from ingredient import rule,event,Logic,Port |
22 | 22 | |
23 | +# Tkinter の unbind には、複数のコールバックをバインドしている際に funcid オプションで特定のコールバックを解除しようとしてもすべて解除されてしまうバグがあるので、その対処 | |
24 | +# http://www.velocityreviews.com/forums/t649198-p2-tkinter-unbinding.html | |
25 | +def unbind(widget, sequence, funcid): | |
26 | + '''unbind funcid callback for sequence on widget | |
27 | + preserve other binding in case of multiple bindings. | |
28 | + ''' | |
29 | + #construct a string containing existing binding minus funcid one | |
30 | + remain_bindings = "\n".join([e for e in widget.bind(sequence).split("\n") if e and e.find(funcid) == -1 ]) | |
31 | + widget.tk.call('bind', widget, sequence,remain_bindings) | |
32 | + | |
23 | 33 | def editable(logic): |
24 | - ''' | |
25 | - コントロールパネルで自動生成可能なポートを返す | |
34 | + '''コントロールパネルで自動生成可能なポートを返す | |
26 | 35 | ''' |
27 | 36 | MYTYPES = (types.IntType,types.FloatType,types.StringType, |
28 | 37 | numpy.float64,numpy.int64,tkext.SpecificTuple,tkext.Selection) |
@@ -570,6 +579,8 @@ | ||
570 | 579 | self.canvas.nodefollower.follow(node,CanvasNode(self.canvas,node)) |
571 | 580 | def selectport(self,e): |
572 | 581 | #FIXME: 別階層ポートも追加できるようにする |
582 | + if not self.canvas.selectedports: # 選択したポートがファーストアイテムならラバーストリングを配置する | |
583 | + CanvasRubberString(self.canvas,loc=self.loc,mouse_loc=(e.x,e.y)) | |
573 | 584 | # 実体ポートを選択バッファに追加する |
574 | 585 | self.canvas.selectedports.append(self.substance) |
575 | 586 | # もしバッファに二つ溜まっていたらリンクする |
@@ -578,6 +589,10 @@ | ||
578 | 589 | for o in subst2().container.observers: |
579 | 590 | subst1().link(o) |
580 | 591 | del self.canvas.selectedports[:] |
592 | + # ラバーストリングのインスタンスを探して廃棄する | |
593 | + for item in self.canvas.items: | |
594 | + if isinstance(item,CanvasRubberString): | |
595 | + item.destroy() | |
581 | 596 | def unlink(self): |
582 | 597 | ''' |
583 | 598 | 自身をアンリンクする |
@@ -641,6 +656,37 @@ | ||
641 | 656 | linkitem().destroy() |
642 | 657 | CanvasItem.destroy(self) |
643 | 658 | |
659 | +class CanvasRubberString(CanvasItem): | |
660 | + def __init__(self,canvas,tag=None,loc=(0,0),mouse_loc=(0,0)): | |
661 | + CanvasItem.__init__(self,canvas,tag,loc) | |
662 | + self._drag = canvas.bind("<Motion>",self.drag,'+') | |
663 | + self.mouse_loc = mouse_loc | |
664 | + self.draw(self.shape) | |
665 | + # self.lower() | |
666 | + @property | |
667 | + def shape(self): | |
668 | + x,y = self.mouse_loc[0] - self.loc[0], self.mouse_loc[1] - self.loc[1] | |
669 | + # マウスポインタの最上位にラバーストリングが必ず配置されてしまうことを防ぐ | |
670 | + if x ** 2 + y ** 2 > 25.: | |
671 | + r = numpy.sqrt(x ** 2 + y ** 2) - 5 | |
672 | + theta = numpy.arctan2(y,x) | |
673 | + x = int(r * numpy.cos(theta)) | |
674 | + y = int(r * numpy.sin(theta)) | |
675 | + return [('line',((0,0),(x,y)),{'width':1,'dash':[3,2]})] | |
676 | + def drag(self,e): | |
677 | + self.mouse_loc = (e.x,e.y) | |
678 | + self.erase() | |
679 | + self.draw(self.shape) | |
680 | + # self.lower() | |
681 | + def destroy(self): | |
682 | + unbind(self.canvas,'<Motion>',funcid=self._drag) | |
683 | + self.erase() | |
684 | + CanvasItem.destroy(self) | |
685 | +# def lower(self): | |
686 | +# for id in self.cid: | |
687 | +# if self.canvas: | |
688 | +# self.canvas.lower(id) | |
689 | + | |
644 | 690 | class CanvasLink(CanvasItem): |
645 | 691 | def __init__(self,canvas,nodeitem,portitem,tag=None,loc=(0,0)): |
646 | 692 | CanvasItem.__init__(self,canvas,tag,loc) |
@@ -896,7 +942,7 @@ | ||
896 | 942 | item.destroy() |
897 | 943 | del self.scrap[:] |
898 | 944 | # イベントループを遅延再起動 |
899 | - self.after(500,self.loop) | |
945 | + self.after(100,self.loop) | |
900 | 946 | def populate_logics(self): |
901 | 947 | # ルート直下のロジックをキャンバス上に配置する |
902 | 948 | for logic in self.root.children.itervalues(): |