summaryrefslogtreecommitdiff
path: root/cad/src/commands/BuildAtoms/BondTool_Command.py
blob: 096aacc79c9ecfee7739198be923c066691d7a97 (plain)
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# Copyright 2008 Nanorex, Inc.  See LICENSE file for details.
"""

@author: Ninad
@copyright: 2008 Nanorex, Inc.  See LICENSE file for details.
@version: $Id$

History:
2008-07-30: Created to refactor Build Atoms command (currently called
BuildAtoms_Command).

TODO:

- Classes created to refactor BuildAtoms_Command (rather 'BuildChunks' command)
to be revised further.
- document
- REVIEW: _reusePropMgr_of_parentCommand -- this is an experimental method
that will fit in the NEW command API (2008-07-30) . to be revised/ renamed.
e.g. command_reuse_PM etc.

- Update methods (e.g. self.propMgr.updateMessage() need to be called
by a central method such as command_update_* or PM._update_UI_*.
"""

from commands.BuildAtoms.BuildAtoms_Command import BuildAtoms_Command
from commands.BuildAtoms.BondTool_GraphicsMode import DeleteBondTool_GraphicsMode
from commands.BuildAtoms.BondTool_GraphicsMode import BondTool_GraphicsMode
from model.bond_constants import V_SINGLE, V_DOUBLE, V_TRIPLE, V_AROMATIC, V_CARBOMERIC, V_GRAPHITE
from utilities.constants import CL_SUBCOMMAND
from model.elements import Singlet
import foundation.env as env
from utilities.Log import orangemsg


class BondTool_Command(BuildAtoms_Command):
    """
    Each of the subclass of this class represent a temporary command that
    will act like 'activating a tool'. Example: when user clicks on single Bonds
    tool, it will enter Single Bond Tool command. , suspending the Build Atoms
    default command.
    """

    GraphicsMode_class = BondTool_GraphicsMode

    FlyoutToolbar_class = None

    featurename = 'Build Atoms Mode/BondTool'
    commandName = 'BOND_TOOL'

    command_should_resume_prevMode = False
    command_has_its_own_PM = False

    currentActiveTool = 'BONDS_TOOL'

    _suppress_apply_bondTool_on_selected_atoms = False


    #class constants for the NEW COMMAND API -- 2008-07-30
    command_level = CL_SUBCOMMAND
    command_parent = 'DEPOSIT'

    def command_entered(self):
        """
        Overrides superclass method.
        @see: baseCommand.command_entered() for documentation
        """
        super(BondTool_Command, self).command_entered()
        self._apply_bondTool_on_selected_atoms()
        name = self.getBondTypeString()
        if name:
            msg = "Click bonds or bondpoints to make them %ss." % name
        else:
            msg = "Select a bond tool and then click on bonds or "\
                "bondpoints to convert them to a specific bond type."
        self.propMgr.updateMessage(msg)

    def getBondType(self):
        return V_SINGLE

    def getBondTypeString(self):
        """
        Overridden in subclasses.
        """
        return ''


    def _apply_bondTool_on_selected_atoms(self):
        """
        Converts the bonds between the selected atoms to one specified by
        self.graphicsMode..bondclick_v6. Example: When user selects all atoms in
        a nanotube and clicks 'graphitic' bond button, it converts all the
        bonds between the selected atoms to graphitic bonds.
        @see: self.activateBondsTool()
        @see: self.changeBondTool()
        @see: bond_utils.apply_btype_to_bond()
        @see: BuildAtoms_GraphicsMode.bond_change_type()
        """
        #Method written on 2008-05-04 to support NFR bug 2832. This need to
        #be reviewed for further optimization (not urgent) -- Ninad
        #This flag is set while activating the bond tool.
        #see self.activateBondsTool()
        if self._suppress_apply_bondTool_on_selected_atoms:
            return

        bondTypeString = self.getBondTypeString()


        #For the history message
        converted_bonds = 0
        non_converted_bonds = 0
        deleted_bonds = 0
        #We wil check the bond dictionary to see if a bond between the
        #selected atoms is already operated on.
        bondDict = {}

        bondList = []
        #all selected atoms
        atoms = self.win.assy.selatoms.values()
        for a in atoms:
            for b in a.bonds[:]:
                #If bond 'b' is already in the bondDict, skip this
                #iteration.
                if bondDict.has_key(id(b)):
                    continue
                else:
                    bondDict[id(b)] = b
                #neigbor atom of the atom 'a'
                neighbor = b.other(a)

                if neighbor.element != Singlet and neighbor.picked:
                    bond_type_changed = self.graphicsMode.bond_change_type(
                        b,
                        allow_remake_bondpoints = True,
                        suppress_history_message = True
                    )
                    if bond_type_changed:
                        converted_bonds += 1
                    else:
                        non_converted_bonds += 1


        msg = "%d bonds between selected atoms "\
            "converted to %s" %(converted_bonds,
                                bondTypeString)
        msg2 = ''
        if non_converted_bonds:
            msg2 = orangemsg(" [Unable to convert %d "\
                             "bonds to %s]"%(non_converted_bonds,
                                             bondTypeString))
        if msg2:
            msg += msg2

        if msg:
            env.history.message(msg)

        self.glpane.gl_update()



    #TEMPORARILY override the is*ToolActive methods in BuildAtoms_Command.
    #These methods will go away when BuildAtoms command starts treating
    #each tool as a subcommand.
    def isAtomsToolActive(self):
        """
        Tells whether the Atoms Tool is active (boolean)
        """
        return False

    def isBondsToolActive(self):
        """
        Tells whether the Bonds Tool is active (boolean)
        """
        return True

    def isDeletBondsToolActive(self):
        """
        Tells whether the Delete Bonds Tool is active (boolean)
        """
        return False

#####################

#classes need to be in their own module
class SingleBondTool(BondTool_Command):

    featurename = 'Build Atoms Mode/SingleBondTool'
    commandName = 'SINGLE_BOND_TOOL'

    command_should_resume_prevMode = True

    def getBondType(self):
        return V_SINGLE

    def getBondTypeString(self):
        """
        Overrides superclass method.
        """
        return 'Single Bond'

class DoubleBondTool(BondTool_Command):
    featurename = 'Build Atoms Mode/DoubleBondTool'
    commandName = 'DOUBLE_BOND_TOOL'

    command_should_resume_prevMode = True

    def getBondType(self):
        return V_DOUBLE

    def getBondTypeString(self):
        """
        Overridden in subclasses.
        """
        return 'Double Bond'

class TripleBondTool(BondTool_Command):
    featurename = 'Build Atoms Mode/TripleBondTool'
    commandName = 'TRIPLE_BOND_TOOL'

    command_should_resume_prevMode = True

    def getBondType(self):
        return V_TRIPLE

    def getBondTypeString(self):
        """
        Overridden in subclasses.
        """
        return 'Triple Bond'

class AromaticBondTool(BondTool_Command):
    featurename = 'Build Atoms Mode/AromaticBondTool'
    commandName = 'AROMATIC_BOND_TOOL'

    command_should_resume_prevMode = True

    def getBondType(self):
        return V_AROMATIC

    def getBondTypeString(self):
        """
        Overridden in subclasses.
        """
        return 'Aromatic Bond'

class GraphiticBondTool(BondTool_Command):
    featurename = 'Build Atoms Mode/GraphiticBondTool'
    commandName = 'GRAPHITIC_BOND_TOOL'

    command_should_resume_prevMode = True

    def getBondType(self):
        return V_GRAPHITE

    def getBondTypeString(self):
        """
        Overridden in subclasses.
        """
        return 'Graphitic Bond'

class DeleteBondTool(BondTool_Command):
    GraphicsMode_class = DeleteBondTool_GraphicsMode
    featurename = 'Build Atoms Mode/DeleteBondTool'
    commandName = 'DELETE_BOND_TOOL'

    command_should_resume_prevMode = True

    def _apply_bondTool_on_selected_atoms(self):
        """
        Converts the bonds between the selected atoms to one specified by
        self.graphicsMode..bondclick_v6. Example: When user selects all atoms in
        a nanotube and clicks 'graphitic' bond button, it converts all the
        bonds between the selected atoms to graphitic bonds.
        @see: self.activateBondsTool()
        @see: self.changeBondTool()
        @see: bond_utils.apply_btype_to_bond()
        @see: BuildAtoms_GraphicsMode.bond_change_type()
        """
        #Method written on 2008-05-04 to support NFR bug 2832. This need to
        #be reviewed for further optimization (not urgent) -- Ninad
        #This flag is set while activating the bond tool.
        #see self.activateBondsTool()
        if self._suppress_apply_bondTool_on_selected_atoms:
            return

        deleted_bonds = 0
        #We wil check the bond dictionary to see if a bond between the
        #selected atoms is already operated on.
        bondDict = {}
        bondList = []
        #all selected atoms
        atoms = self.win.assy.selatoms.values()
        for a in atoms:
            for b in a.bonds[:]:
                #If bond 'b' is already in the bondDict, skip this
                #iteration.
                if bondDict.has_key(id(b)):
                    continue
                else:
                    bondDict[id(b)] = b
                #neigbor atom of the atom 'a'
                neighbor = b.other(a)

                if neighbor.element != Singlet and neighbor.picked:
                    b.bust()
                    deleted_bonds += 1

        msg = "Deleted %d bonds between selected atoms"%deleted_bonds
        env.history.message(msg)
        self.glpane.gl_update()