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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
# Copyright 2008 Nanorex, Inc. See LICENSE file for details.
"""
@author: Ninad
@copyright: 2008 Nanorex, Inc. See LICENSE file for details.
@version:$Id$
History:
2008-05-13 Created
TODO: 2008-05-13
This is an initial implementation subjected to heavy revision. Initial purpose
is just to RESIZE given structures (of same type) together. Can be extended
in future but needs refactoring then.
- This class assumes attr currentStruct for the current command and also
assumes a method currentStruct.getAxisEndPoints! Note that this will be true
for currentStruct = DnaSegment, CntSegment BUT NOT FOR DnaStrand
so when we support resizing multiple dnastrands, this must be refactored.
- Created to initially support resizing multiple dna segments. Can be extended
for other commands such as strand, nanotube resizing.
This class assumes certain things such as the struct being edited will have
resize handles. If it is not the case, refactoring is needed to move methods
such as self.updateAverageEndPoints() to the subclasses.
- Need safety features to make sure that structures provided by the
list of structures (in self._structList) are of valid structure type (e.g.
if you are resizing multiple Dnasegments, self._structList must contain
all instances of DnaSegment only.
"""
from geometry.VQT import V
class EditCommand_StructureList:
def __init__(self, editCommand, structList = ()):
self.editCommand = editCommand
self._structList = []
self.setStructList(structList = structList)
#self.end1 , self.end2 are the average endpoints calculated using
#endpoints of structs within structList.
self.end1 = None
self.end2 = None
#TODO: revise the following.
#@see self._getAverageEndPoints() where these lists are being used.
#@see: comments in DnaSegmentList.getAxisEndAtomAtPosition()
self.endPoints_1 = []
self.endPoints_2 = []
self.endPointsDict = {} #unused as of 2008-05-13 (used in some commented
#out code)
self.updateAverageEndPoints()
def parent_node_of_class(self, clas):
"""
Returns parent node of the class <clas> for the
'currentStructure' of self's editcommand being edited. If there is no
currentStructure, it returns the parent node of specified class
of the 'first structure' in the self._structList.
"""
if self.editCommand.currentStruct:
if self.editCommand.currentStruct.killed():
return None
return self.editCommand.currentStruct.parent_node_of_class(clas)
if not self._structList:
return None
firstStruct = self._structList[0]
if firstStruct is None:
return None
if firstStruct.killed():
return None
return firstStruct.parent_node_of_class(clas)
def killed(self):
"""
Always returns False as of 2008-05-16. There is no UI to 'delete'
this list object. (its internal) This method is implemented just to
handle the calls in , for example, EditCommand.hasValidStructure()
@see: MultipleDnaSegment_EditCommand.hasValidStructure()
"""
return False
def isEmpty(self):
"""
Returns True if if the self._sturctList is empty.
"""
if len(self._structList) == 0:
return True
return False
def updateStructList(self):
"""
Update the structure list , removing the invalid items in the structure
@see:MultipleDnaSegmentResize_PropertyManager.model_changed()
@see: self.getstructList()
"""
#@TODO: Should this always be called in self.getStructList()??? But that
#could be SLOW because that method gets called too often by
#the edit command's graphics mode.
def func(struct):
if struct is not None and not struct.killed():
if not struct.isEmpty():
return True
return False
new_list = filter( lambda struct:
func(struct) ,
self._structList )
if len(new_list) != len(self._structList):
self._structList = new_list
def getStructList(self):
"""
Returns the list of structures being edited together.
@see: MultipleDnaSegmentResize_graphicsMode._drawHandles()
"""
#Should we call self.updateStructList() here?? But that could be
#too slow because this method is called quite often in the
#graphics mode.draw of the command
return self._structList
def setStructList(self, structList = () ):
"""
Replaces the list of structures (self._structList)
with the given one.
@param structList: List containing the structures to be edited at once
This list will replace the existing
self._structList
@type: list
@see: MultipleSegmentResize_EditCommand.setStructList()
(calls this method. )
"""
self._structList = list(structList)
self.updateAverageEndPoints()
def addToStructList(self, struct):
"""
Add the given structure to the list of structures being edited together.
@param struct: Structure to be added to the self._structList
"""
if struct is not None and not struct in self._structList:
self._structList.append(struct)
self.updateAverageEndPoints()
def removeFromStructList(self, struct):
"""
Remove the given structure from the list of structures being edited
together.
@param struct: Structure to be removed from the self._structList
"""
if struct in self._structList:
self._structList.remove(struct)
self.updateAverageEndPoints()
def updateAverageEndPoints(self):
"""
Update self's average end points.
"""
#(may need refactoring in future)
self.end1, self.end2 = self._getAverageEndPoints()
def _getAverageEndPoints(self):
"""
Subclasses should override this method. Default implementation assumes an
attr (method) getAxisEndPoints for structures in
self._structList
This is not True for some structures such as DnaStrand.
"""
endPoint1 = V(0.0, 0.0, 0.0)
endPoint2 = V(0.0, 0.0, 0.0)
n1 = 0
n2 = 0
self.endPoints_1 = []
self.endPoints_2 = []
self.endPointsDict = {}
for struct in self._structList:
end1, end2 = struct.getAxisEndPoints()
if end1 is not None:
endPoint1 += end1
self.endPoints_1.append(end1)
if end2 is not None:
endPoint2 += end2
n2 += 1
self.endPoints_2.append(end2)
n1 = len(self.endPoints_1)
n2 = len(self.endPoints_2)
if n1 > 0:
endPoint1 /= n1
self.endPoints_1.append(endPoint1)
##self.endPointsDict[endPoint1] = self.endPoints_1
if n2 > 0:
endPoint2 /= n2
self.endPoints_2.append(endPoint2)
##self.endPointsDict[endPoint2] = self.endPoints_2
return (endPoint1, endPoint2)
def getAxisEndPoints(self):
"""
@TODO: Revise/ Refactor this. This needs to be implemented in a subclass
rather than here because not all structures that this class will support
have an attr getAxisEndPoints. (e.g. DnaStrand). (although several
strutures will have this attr)
"""
currentStruct = self.editCommand.currentStruct
if currentStruct and hasattr(currentStruct, 'getAxisEndPoints'):
return self.editCommand.currentStruct.getAxisEndPoints()
self.updateAverageEndPoints()
return (self.end1, self.end2)
def getProps(self):
"""
Returns the properties of editCommand's currentStruct. If there is
no currentStruct, it uses the firstStruct in self._structList
"""
if self.editCommand.currentStruct:
return self.editCommand.currentStruct.getProps()
if not self._structList:
return ()
firstStruct = self._structList[0]
if firstStruct is None:
return ()
return firstStruct.getProps()
def setProps(self, props):
"""
TODO: expand this method
"""
pass
|