-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpalette_dnd.py
142 lines (121 loc) · 5.19 KB
/
palette_dnd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import Tkinter as tk
import Tkdnd
from palette_info import StartFieldInfo, ConnectorInfo, FieldInfo, EndFieldInfo
from palette_view import FieldView, StartFieldView, ConnectorView, EndFieldView
from workspace import Workspace
def MouseInWidget(Widget ,Event):
x = Event.x_root - Widget.winfo_rootx()
y = Event.y_root - Widget.winfo_rooty()
return (x ,y)
class Draggable():
def __init__(self, parent, frame):
self.Canvas = None
self.OriginalCanvas = None
self.Label = None
self.OriginalLabel = None
self.OffsetX = 20
self.OffsetY = 10
self.Parent = parent
self.INFO_ID = frame
def dnd_end(self, Target, Event):
# self.Label.invoke()
if self.Canvas == None and self.OriginalCanvas == None:
return
if self.Canvas == None and self.OriginalCanvas <> None:
self.ID = self.OriginalID
self.Label = self.OriginalLabel
self.Canvas.dnd_enter(self, Event)
return
# At this point we know that self.Canvas is not None, which means we have an
# label of ourself on that canvas. Bind <ButtonPress> to that label so the
# the user can pick us up again if and when desired.
self.Label.bind('<ButtonPress>', self.Press)
# If self.OriginalCanvas exists then we were an existing object and our
# original label is still around although hidden. We no longer need
# it so we delete it.
if self.OriginalCanvas:
# info = Tree.current.fields[self.Frame]
# lbl = self.OriginalLabel
# print(self.OriginalLabel.test1.get())
self.OriginalCanvas.delete(self.OriginalID)
self.OriginalCanvas = None
self.OriginalID = None
self.OriginalLabel = None
def view_from_info(self, Canvas, info):
if isinstance(info, StartFieldInfo):
view = StartFieldView(Canvas, self.INFO_ID)
elif isinstance(info, ConnectorInfo):
view = ConnectorView(Canvas, self.INFO_ID)
elif isinstance(info, FieldInfo):
view = FieldView(Canvas, self.INFO_ID)
elif isinstance(info, EndFieldInfo):
view = EndFieldView(Canvas, self.INFO_ID)
else:
raise Exception('Info is not supported')
view.resurrect(info)
view.init_vars()
return view
def Appear(self, Canvas, XY):
if self.Canvas:
return
self.X, self.Y = XY
self.X = Canvas.canvasx(self.X)
self.Y = Canvas.canvasy(self.Y)
if self.INFO_ID is not None:
info = Workspace.current.get_tree().fields[self.INFO_ID]
self.Label = self.view_from_info(Canvas, info)
else:
raise Exception('Info_ID is None')
# Display the label on a window on the canvas. We need the ID returned by
# the canvas so we can move the label around as the mouse moves.
x = self.X - self.OffsetX
y = self.Y - self.OffsetY
self.ID = Canvas.create_window(x, y, window=self.Label, anchor="nw")
# Note the canvas on which we drew the label.
self.Canvas = Canvas
self.Label.VIEW_ID = self.ID
Workspace.current.get_tree().views[self.INFO_ID] = self.Label
def Vanish(self, All=0):
"""
If there is a label representing us on a canvas, make it go away.
if self.Canvas is not None, that implies that "Appear" had prevously
put a label representing us on the canvas and we delete it.
if "All" is true then we check self.OriginalCanvas and if it not None
we delete from it the label which represents us.
"""
if self.Canvas:
self.Canvas.delete(self.ID)
self.Canvas = None
del self.ID
del self.Label
if All and self.OriginalCanvas:
# Delete label representing us from self.OriginalCanvas
self.OriginalCanvas.delete(self.OriginalID)
self.OriginalCanvas = None
del self.OriginalID
del self.OriginalLabel
def Move(self, XY):
assert self.Canvas, "Can't move because we are not on a canvas"
self.X, self.Y = XY
self.X = self.Canvas.canvasx(self.X)
self.Y = self.Canvas.canvasy(self.Y)
self.Canvas.coords(self.ID, self.X - self.OffsetX, self.Y - self.OffsetY)
def Press(self, Event):
# Save our current status
self.OriginalCanvas = self.Canvas
self.OriginalID = self.ID
self.OriginalLabel = self.Label
# Make phantom invisible
self.Label.__hide__()
# Say we have no current label
self.ID = None
self.Label = None
self.Canvas = None
# Ask Tkdnd to start the drag operation
if Tkdnd.dnd_start(self, Event):
# Save where the mouse pointer was in the label so it stays in the
# same relative position as we drag it around
self.OffsetX, self.OffsetY = MouseInWidget(self.OriginalLabel, Event)
# Draw a label of ourself for the user to drag around
XY = MouseInWidget(self.OriginalCanvas, Event)
self.Appear(self.OriginalCanvas, XY)