forked from UM-ANCR/DNA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Component.py
181 lines (155 loc) · 7.23 KB
/
Component.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
'''
* Component.py
*
* Assumes the selected node is of type component;
* adds a box where demands of this component can be
* specified
*
* Major functionalities include:
* demand box / create new demand
* update sizes of nodes if current system is not 'All'
* save/repopulate
*
'''
from Tkinter import *
import tkSimpleDialog
import networkx as nx
class Component(Frame):
def __init__(self, parent, leftFrame, index, G, manager):
Frame.__init__(self, parent)
self.parent = parent
self.leftFrame = leftFrame
self.index = index
self.G = G
self.manager = manager
self.systemDict = {}
self.color = "dark gray"
self.initUI()
def createDemandLabel(self):
self.demandGroup.columnconfigure(0, weight=1)
self.demandGroup.columnconfigure(1, weight=1)
# 'create new demand' button
self.createDemandBtn = Button(self.demandGroup, text="New Demand", command=self.createNewDemand, bg=self.color, highlightbackground=self.color)
self.createDemandBtn.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky=E+W)
self.numDemands = 0
# create a new demand entry for every system in our manager list (in Manager.py)
for systemLabel in self.manager.systems:
self.createNewDemand(systemLabel)
def createNewDemand(self, label=None):
# If no label was provided as a parameter, prompt for a label
if label == None:
label = tkSimpleDialog.askstring(title="Label", prompt="Enter a Label Name") # Prompt for label
# if user hit 'Cancel' in dialog window, label=None; return from this function
if label == None:
return
# else user didn't hit 'Cancel', so add the user input as a new system in our manager
self.manager.addSystem(label)
# Create new Label and corresponding entry box
self.newDemandLabel = Label(self.demandGroup, text=label, bg=self.color)
self.newDemandLabel.grid(row=0+self.numDemands, column=0, sticky=E+W)
newEntry = Entry(self.demandGroup, highlightbackground=self.color, width=9)
newEntry.grid(row=0+self.numDemands, column=1, padx=5, sticky=E+W)
self.systemDict[label] = newEntry # save the entry widget in the dictionary systemDict
# move 'Create New' button down
self.createDemandBtn.grid(row=1+self.numDemands, column=0, columnspan=2, padx=5, pady=5, sticky=E+W)
self.numDemands += 1
# add the new demand/system to the main toolbar dropdown
if label not in self.leftFrame.optionList:
self.leftFrame.optionList.insert(len(self.leftFrame.optionList)-2, label)
self.leftFrame.dropdown.destroy()
self.leftFrame.dropdown = OptionMenu(self.leftFrame.toolbar, self.leftFrame.v,
*self.leftFrame.optionList, command=self.leftFrame.newOptionMenu)
self.leftFrame.dropdown.configure(highlightbackground="light blue", bg='light blue')
self.leftFrame.dropdown.pack(side='left')
def createGeometry(self):
self.geoGroup = LabelFrame(self.parent, text="Geometry", bg=self.color)
self.geoGroup.grid(row=2, padx=10, sticky=E+W)
# x coord
self.xLabel = Label(self.geoGroup, text="x", bg=self.color)
self.xLabel.grid(row=0, column=1, padx=(5, 0), pady=(0, 5))
self.xEntry = Entry(self.geoGroup, highlightbackground=self.color, width=5)
self.xEntry.grid(row=0, column=2, pady=(0, 5))
self.xEntry.insert(0, 0) # initialize to 0
# y coord
self.yLabel = Label(self.geoGroup, text="y", bg=self.color)
self.yLabel.grid(row=0, column=3, padx=(5, 0), pady=(0, 5))
self.yEntry = Entry(self.geoGroup, highlightbackground=self.color, width=5)
self.yEntry.grid(row=0, column=4, pady=(0, 5))
self.yEntry.insert(0, 0)
# z coord
self.zLabel = Label(self.geoGroup, text="z", bg=self.color)
self.zLabel.grid(row=0, column=5, padx=(5, 0), pady=(0, 5))
self.zEntry = Entry(self.geoGroup, highlightbackground=self.color, width=5)
self.zEntry.grid(row=0, column=6, pady=(0, 5))
self.zEntry.insert(0, 0)
def updateNodeSizes(self):
if self.leftFrame.v.get() != 'All' and self.leftFrame.v.get() != 'Create New':
self.leftFrame.minDemand = 1000000000
self.leftFrame.maxDemand = -1
visibleNodes = []
# for each node on the canvas
for nodeitem in self.leftFrame.systemsCanvas.find_withtag('node'):
# if it has a demand value for current system we're in
if self.leftFrame.v.get() in self.G.node[nodeitem]:
visibleNodes.append(nodeitem) # add to a list of visible nodes
# find minimum and maximum values for this demand
thisDemand = self.G.node[nodeitem][self.leftFrame.v.get()]
if abs(thisDemand) < self.leftFrame.minDemand:
self.leftFrame.minDemand = abs(thisDemand)
if abs(thisDemand) > self.leftFrame.maxDemand:
self.leftFrame.maxDemand = abs(thisDemand)
# delete old '+' or '-' labels
self.leftFrame.systemsCanvas.delete('label')
# update node sizes
for nodeitem in visibleNodes:
self.leftFrame.normalNodeSize(nodeitem)
self.leftFrame.scaleNodeSize(nodeitem)
def saveNodeAttributes(self):
# save demands values of this node
for x in self.manager.systems:
# if there is a value for this node
if self.systemDict[x].get() != None and self.systemDict[x].get() != '':
# if system doesn't exist in NetworkX already OR if the curr value in NetworkX isn't updated, save the curr value
if (x not in self.G.node[self.index]) or (self.G.node[self.index][x] != int(self.systemDict[x].get())):
self.G.node[self.index][x] = int(self.systemDict[x].get())
# else if a previous value was cleared
elif x in self.G.node[self.index] and self.systemDict[x].get() == '':
# if we're not in 'All', hide this node and the edges connected to it bc there isn't a demand value anymore
if self.leftFrame.v.get() != 'All':
nodeCoords = self.leftFrame.systemsCanvas.coords(self.index)
overlapped = self.leftFrame.systemsCanvas.find_overlapping(nodeCoords[0], nodeCoords[1], nodeCoords[2], nodeCoords[3])
for edge in overlapped:
if self.leftFrame.checkTag(edge) == 'edge':
self.leftFrame.systemsCanvas.itemconfig(edge, state='hidden')
self.leftFrame.systemsCanvas.itemconfig(self.index, state='hidden')
del self.G.node[self.index][x]
# save geometry values of this node
titles = ['x', 'y', 'z']
values = [self.xEntry.get(), self.yEntry.get(), self.zEntry.get()]
# for each field, check if coord is updated in NetworkX; if not, save and add to 'updated'
for i in range(0, len(titles)):
if (titles[i] not in self.G.node[self.index]) or (self.G.node[self.index][titles[i]] != values[i]):
self.G.node[self.index][titles[i]] = values[i]
self.updateNodeSizes()
def repopulateNodeData(self):
# repopulate demand values
for x in self.manager.systems:
if x in self.G.node[self.index]:
self.systemDict[x].delete(0, END)
self.systemDict[x].insert(0, self.G.node[self.index][x])
# repopulate x, y, z values
if 'x' in self.G.node[self.index]:
self.xEntry.delete(0, END)
self.xEntry.insert(0, self.G.node[self.index]['x'])
if 'y' in self.G.node[self.index]:
self.yEntry.delete(0, END)
self.yEntry.insert(0, self.G.node[self.index]['y'])
if 'z' in self.G.node[self.index]:
self.zEntry.delete(0, END)
self.zEntry.insert(0, self.G.node[self.index]['z'])
def initUI(self):
self.demandGroup = LabelFrame(self.parent, text="Demands", bg=self.color)
self.demandGroup.grid(row=1, padx=10, sticky=E+W)
self.createDemandLabel()
self.createGeometry()
self.repopulateNodeData()